#if (FEATURE_MODE == 0)
#include "sys_usw_pon.h"
#include "sys_usw_port_api.h"
#include "sys_usw_scl_api.h"
#include "sys_usw_nexthop_api.h"
#include "sys_usw_vlan_mapping.h"
#include "sys_usw_dmps.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_register.h"

extern int32 sys_usw_nh_add_gem_port_l2edit_8w_outer(uint8 lchip, uint16 logic_dest_port, uint16 gem_vlan);
extern int32 sys_usw_nh_remove_gem_port_l2edit_8w_outer(uint8 lchip, uint16 logic_dest_port);
extern int32 sys_usw_qos_bind_service_logic_dstport(uint8 lchip, uint16 service_id, uint16 logic_dst_port, uint32 gport,uint32 nexthop_ptr);
extern int32 sys_usw_qos_unbind_service_logic_dstport(uint8 lchip, uint16 service_id, uint16 logic_dst_port, uint32 gport);
extern int32 sys_usw_nh_get_vlan_edit_info(uint8 lchip, uint32 nhid, ctc_vlan_egress_edit_info_t* p_vlan_info);
extern uint32 sys_usw_nh_get_gem_port_l2edit_8w_outer_index(uint8 lchip, uint16 logic_dest_port);
extern uint32 sys_usw_nh_xgpon_flooding_en(uint8 lchip, uint32 logic_port, uint8 enable);

#define SYS_PON_DBG_OUT(level, FMT, ...) \
    do { \
        CTC_DEBUG_OUT(pon, pon, PON_SYS, level, FMT, ##__VA_ARGS__); \
    } while (0)

#define SYS_PON_DBG_FUNC()          SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__)
#define SYS_PON_DBG_INFO(FMT, ...)  SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_INFO, FMT, ##__VA_ARGS__)
#define SYS_PON_DBG_ERROR(FMT, ...) SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, FMT, ##__VA_ARGS__)
#define SYS_PON_DBG_PARAM(FMT, ...) SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, FMT, ##__VA_ARGS__)
#define SYS_PON_DBG_DUMP(FMT, ...)  SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, FMT, ##__VA_ARGS__)

#define CTC_PON_PRI_SVRANG_CVID       1
#define CTC_PON_PRI_FLEX              3
#define CTC_PON_PRI_TUN_SVRANG_CVID   4
#define CTC_PON_PRI_TUN_FLEX          6
#define CTC_PON_FLEX_EPRI         2

/*alloc 1D pointer's memory */
#define MALLOC_PON_POINTER(T, p) \
    { \
        p = (T*)mem_malloc(MEM_PON_MODULE, sizeof(T)); \
    }

#define SYS_PON_LOCK(lchip) \
    if(p_usw_pon_master[lchip]->mutex) sal_mutex_lock(p_usw_pon_master[lchip]->mutex)

#define SYS_PON_UNLOCK(lchip) \
    if(p_usw_pon_master[lchip]->mutex) sal_mutex_unlock(p_usw_pon_master[lchip]->mutex)


struct sys_pon_port_db_s
{
    uint8 enable;
    uint8 vlan_range_grp;
    uint16 flex_onu_cnt;
    uint16 flex_pon_cnt;
    uint16 logic_port;
    uint16 vlan_range_grp_cnt;
};
typedef struct sys_pon_port_db_s sys_pon_port_db_t;


struct sys_pon_gem_port_db_s
{
    uint32 gport;
    uint32 tunnel_value;

    uint16 logic_port;
    uint16 ref_cnt;

    uint16  igs_policer_id;
    uint16  egs_service_id;
    uint32  pass_through_en :1;
    uint32  mac_security    :3;
    uint32  is_flooding     :1;
    uint32  rsv             :27;

};
typedef struct sys_pon_gem_port_db_s sys_pon_gem_port_db_t;

struct sys_pon_vlan_port_db_s
{
    uint32 vlan_port_id;
    uint32 calc_key_len[0];

    sys_pon_gem_port_db_t* p_gem_port_db;

    ctc_scl_vlan_edit_t igs_vlan_action;  /* Ingress vlan action */
    ctc_scl_vlan_edit_t egs_vlan_action;   /* Egress vlan action */

    uint8 criteria;
    uint8 scl_id;
    uint8  match_scos;
    uint8  match_scos_valid;
    uint32 flag;
    
    uint32 gport;
    uint32 tunnel_value;
    
    uint16 match_svlan;
    uint16 match_cvlan;
    uint16 match_svlan_end;
    uint16 match_cvlan_end;
    
    uint16 pkt_svlan;
    uint16 pkt_cvlan;
    uint32 logic_port;
    
    uint32 logic_dest_port;
    uint32 acl_logic_port;
    
    uint32 xlate_nhid;
    uint16 vn_tag;
    uint16 fid;
    
    uint16 igs_policer_id;
    uint8 egs_vlan_mapping_en;
    uint8 pass_through_en;
    uint32 scl_eid;
    
    uint8 igs_vlan_mapping_use_flex;
};
typedef struct sys_pon_vlan_port_db_s sys_pon_vlan_port_db_t;


struct sys_pon_master_s
{
    ctc_hash_t* gem_port_hash;
    ctc_hash_t* vlan_port_hash;
    sys_pon_port_db_t* p_port_db;
    sal_mutex_t* mutex;
    uint8 opf_vlan_range_group_id;
    uint8 pon_mode;

};
typedef struct sys_pon_master_s sys_pon_master_t;


sys_pon_master_t* p_usw_pon_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

#define SYS_PON_INIT_CHECK(lchip) \
do {\
    if(NULL == p_usw_pon_master[lchip]) return CTC_E_NOT_INIT;\
}while(0);


#define SYS_PON_TUNNEL_VLAN_ID_CHECK(val) \
do { \
    if ((val) > 0xFFFF)\
    {\
        return CTC_E_BADID;\
    }\
}while(0)

    
#define SYS_PON_SCL_ID_CHECK(p_vlan_port) \
    do { \
        if (CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_SCL_ID))\
        {\
            if(p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN)\
            {\
                if(p_vlan_port->scl_id > 1)\
                    return CTC_E_INVALID_CONFIG;\
            }\
            else\
            {\
                if(p_vlan_port->scl_id != 2 && p_vlan_port->scl_id != 3)\
                    return CTC_E_INVALID_CONFIG;\
            }\
        }\
    }while(0)



#define SYS_PON_ERROR_RETURN_UNLOCK(op)               \
    do                                                          \
    {                                                           \
        int32 rv = (op);                                        \
        if (rv < 0)                                             \
        {                                                       \
            sal_mutex_unlock(p_usw_pon_master[lchip]->mutex);  \
            return rv;                                          \
        }                                                       \
    } while (0)

#define ENCODE_SCL_VLAN_ENTRY_ID(entry_id) (3 << 24 |(entry_id))
#define ENCODE_SCL_UPLINK_ENTRY_ID(fid, port) (5<<24 | (port)<<13 |(fid))

#define SYS_PON_SET_VLANMAPPING_KEY_TYPE()  \
{\
    CTC_SET_FLAG(vlan_mapping.key, CTC_VLAN_MAPPING_KEY_SVID); \
    vlan_mapping.old_svid = p_vlan_port_db->match_svlan;\
    if(p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN)\
    {\
        CTC_SET_FLAG(vlan_mapping.key, CTC_VLAN_MAPPING_KEY_CVID);\
        vlan_mapping.old_cvid = p_vlan_port_db->match_cvlan;\
    }\
    else if(p_vlan_port_db->match_scos_valid)\
    {\
        CTC_SET_FLAG(vlan_mapping.key, CTC_VLAN_MAPPING_KEY_STAG_COS);\
        vlan_mapping.old_scos = p_vlan_port_db->match_scos;\
    }\
}

STATIC uint32
_sys_usw_pon_vlan_range_group_en(uint8 lchip, uint32 gport, uint32 enable)
{
    sys_pon_port_db_t* p_port_db = NULL;
    sys_usw_opf_t opf;
    ctc_vlan_range_info_t vlan_range;
    uint16 lport = 0;
    uint32 vlan_range_grp = 0;
    bool is_svlan = FALSE;
    int32 ret = CTC_E_NONE;

    lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport);

    /* DB */
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];
    if (0 == p_port_db->enable)
    {
       return CTC_E_NOT_READY;
    }

    if ((TRUE == enable) && (0 != p_port_db->vlan_range_grp_cnt))
    {
        p_port_db->vlan_range_grp_cnt++;
        return CTC_E_NONE;
    }
    else if ((FALSE == enable) && (0 == p_port_db->vlan_range_grp_cnt))
    {
        return CTC_E_NONE;
    }
    else if ((FALSE == enable) && (0 != p_port_db->vlan_range_grp_cnt))
    {
        p_port_db->vlan_range_grp_cnt--;
    }
    /** Alloc new uni port isolated id*/
    sal_memset(&opf, 0, sizeof(opf));
    opf.pool_type = p_usw_pon_master[lchip]->opf_vlan_range_group_id;
    opf.pool_index = 0;

    if (TRUE == enable)
    {
        CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, 1, &vlan_range_grp));
        p_port_db->vlan_range_grp = vlan_range_grp;
        sal_memset(&vlan_range, 0, sizeof(vlan_range));
        vlan_range.direction = CTC_INGRESS;
        vlan_range.vrange_grpid = vlan_range_grp;
        CTC_ERROR_GOTO(sys_usw_vlan_create_vlan_range(lchip, &vlan_range, TRUE), ret, roll_back_0);
        CTC_ERROR_GOTO(sys_usw_vlan_get_vlan_range_type(lchip, &vlan_range, &is_svlan), ret, roll_back_0);
        CTC_ERROR_GOTO(sys_usw_port_set_vlan_range(lchip, gport, &vlan_range, is_svlan, TRUE), ret, roll_back_0);

        sal_memset(&vlan_range, 0, sizeof(vlan_range));
        vlan_range.direction = CTC_EGRESS;
        vlan_range.vrange_grpid = vlan_range_grp;
        CTC_ERROR_GOTO(sys_usw_vlan_create_vlan_range(lchip, &vlan_range, FALSE), ret, roll_back_0);
        CTC_ERROR_GOTO(sys_usw_vlan_get_vlan_range_type(lchip, &vlan_range, &is_svlan), ret, roll_back_0);
        CTC_ERROR_GOTO(sys_usw_port_set_vlan_range(lchip, gport, &vlan_range, is_svlan, TRUE), ret, roll_back_0);
        p_port_db->vlan_range_grp_cnt++;
    }
    else if ((0 == p_port_db->vlan_range_grp_cnt ) || (CTC_MAX_UINT8_VALUE == enable))
    {
        sal_memset(&vlan_range, 0, sizeof(vlan_range));
        vlan_range.direction = CTC_EGRESS;
        vlan_range.vrange_grpid = p_port_db->vlan_range_grp;
        sys_usw_port_set_vlan_range(lchip, gport, &vlan_range, is_svlan, FALSE);
        sys_usw_vlan_destroy_vlan_range(lchip, &vlan_range);

        sal_memset(&vlan_range, 0, sizeof(vlan_range));
        vlan_range.direction = CTC_INGRESS;
        vlan_range.vrange_grpid = p_port_db->vlan_range_grp;
        sys_usw_vlan_create_vlan_range(lchip, &vlan_range, FALSE);
        sys_usw_vlan_destroy_vlan_range(lchip, &vlan_range);
        sys_usw_opf_free_offset(lchip, &opf, 1, p_port_db->vlan_range_grp);
        p_port_db->vlan_range_grp_cnt = 0;
    }

    return CTC_E_NONE;
roll_back_0:
    if (enable)
    {
        opf.pool_type = p_usw_pon_master[lchip]->opf_vlan_range_group_id;
        opf.pool_index = 0;
        sys_usw_opf_free_offset(lchip, &opf, 1, vlan_range_grp);
    }

    return ret;
}

STATIC uint32
_sys_usw_pon_gem_port_hash_make(sys_pon_gem_port_db_t* p_gem_port_db)
{
    uint32 data[2] = {0};
    uint32 length = 0;

    data[0] = p_gem_port_db->gport;
    data[1] = p_gem_port_db->tunnel_value;
    length = sizeof(uint32)*2;

    return ctc_hash_caculate(length, (uint8*)data);
}

STATIC bool
_sys_usw_pon_gem_port_hash_cmp(sys_pon_gem_port_db_t* p_data0,
                                     sys_pon_gem_port_db_t* p_data1)
{
    if (p_data0->gport == p_data1->gport &&
        p_data0->tunnel_value == p_data1->tunnel_value)
    {
        return TRUE;
    }

    return FALSE;
}

STATIC uint32
_sys_usw_pon_vlan_port_hash_make(sys_pon_vlan_port_db_t* p_vlan_port_db)
{
    uint32 data;
    uint32 length = 0;

    data = p_vlan_port_db->vlan_port_id;

    length = sizeof(uint32);

    return ctc_hash_caculate(length, (uint8*)&data);
}

STATIC bool
_sys_usw_pon_vlan_port_hash_cmp(sys_pon_vlan_port_db_t* p_data0,
                            sys_pon_vlan_port_db_t* p_data1)
{
    if (p_data0->vlan_port_id == p_data1->vlan_port_id)
    {
        return TRUE;
    }

    return FALSE;
}


/*Gem Port*/
#define _____GEM_PORT_____ ""


/* For pon add/remove gem port */
int32
_sys_pon_add_gem_port_hw(uint8 lchip, sys_pon_gem_port_db_t* p_gem_port)
{
    uint32 value = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsGemPortHashKey_m gem_port_key;
    drv_acc_in_t in;
    drv_acc_out_t out;
    sal_memset(&gem_port_key, 0, sizeof(DsGemPortHashKey_m));

    dmps_port_info.gport = p_gem_port->gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &value));
    /*get channel from port */
    SetDsGemPortHashKey(V, channelId_f, &gem_port_key, value);
    SetDsGemPortHashKey(V, gemPort_f, &gem_port_key, p_gem_port->tunnel_value);
    SetDsGemPortHashKey(V, logicSrcPort_f, &gem_port_key, p_gem_port->logic_port);
    SetDsGemPortHashKey(V, logicSrcPortValid_f, &gem_port_key, 1);
    value = (CTC_MACLIMIT_ACTION_DISCARD == p_gem_port->mac_security) || (CTC_MACLIMIT_ACTION_TOCPU == p_gem_port->mac_security);
    SetDsGemPortHashKey(V, macSecurityDiscard_f, &gem_port_key, value);
    value = CTC_MACLIMIT_ACTION_TOCPU == p_gem_port->mac_security;
    SetDsGemPortHashKey(V, macSecurityExceptionEn_f, &gem_port_key, value);
    SetDsGemPortHashKey(V, onuPassThroughEn_f, &gem_port_key, p_gem_port->pass_through_en?0:1);
    SetDsGemPortHashKey(V, userIdLookupDisable_f, &gem_port_key, 0);
    SetDsGemPortHashKey(V, valid_f, &gem_port_key, 1);

    sal_memset(&in, 0, sizeof(in));
    in.type = DRV_ACC_TYPE_ADD;
    in.op_type = DRV_ACC_OP_BY_KEY;
    in.tbl_id    = DsGemPortHashKey_t;
    in.data      = &gem_port_key;
    in.module = DRV_ACC_HASH_MODULE_GEMPORT_HASH;

    CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
    if (out.is_conflict)
    {
        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Gem Port Hash key conflict! \n");
        return CTC_E_HASH_CONFLICT;
    }
        
    return CTC_E_NONE;
}


int32
_sys_pon_remove_gem_port_hw(uint8 lchip, sys_pon_gem_port_db_t* p_gem_port)
{
    DsGemPortHashKey_m gem_port_key;
    drv_acc_in_t in;
    drv_acc_out_t out;
    uint32 chan_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    dmps_port_info.gport = p_gem_port->gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    /*get channel from port */
    sal_memset(&gem_port_key, 0,sizeof(gem_port_key));
    SetDsGemPortHashKey(V, channelId_f, &gem_port_key, chan_id);
    SetDsGemPortHashKey(V, gemPort_f, &gem_port_key, p_gem_port->tunnel_value);
    SetDsGemPortHashKey(V, valid_f, &gem_port_key, 1);

    sal_memset(&in, 0, sizeof(in));
    in.type = DRV_ACC_TYPE_DEL;
    in.op_type = DRV_ACC_OP_BY_KEY;
    in.tbl_id    = DsGemPortHashKey_t;
    in.data      = &gem_port_key;
    in.module = DRV_ACC_HASH_MODULE_GEMPORT_HASH;

    CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));

    return CTC_E_NONE;
}

int32
_sys_pon_get_gem_port_hw_index(uint8 lchip, sys_pon_gem_port_db_t* p_gem_port, uint32* p_index)
{
    DsGemPortHashKey_m gem_port_key;
    drv_acc_in_t in;
    drv_acc_out_t out;
    uint32 chan_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    dmps_port_info.gport = p_gem_port->gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    /*get channel from port */
    sal_memset(&gem_port_key, 0,sizeof(gem_port_key));
    SetDsGemPortHashKey(V, channelId_f, &gem_port_key, chan_id);
    SetDsGemPortHashKey(V, gemPort_f, &gem_port_key, p_gem_port->tunnel_value);
    SetDsGemPortHashKey(V, valid_f, &gem_port_key, 1);

    sal_memset(&in, 0, sizeof(drv_acc_in_t));  
    sal_memset(&out, 0, sizeof(drv_acc_out_t));
    in.type = DRV_ACC_TYPE_LOOKUP;
    in.op_type = DRV_ACC_OP_BY_KEY;
    in.tbl_id    = DsGemPortHashKey_t;
    in.data      = &gem_port_key;
    in.module = DRV_ACC_HASH_MODULE_GEMPORT_HASH;

    CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
    if (out.is_conflict)
    {
        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [PON] Gen port hash key confict , line:%d\n", __LINE__);
        return CTC_E_HASH_CONFLICT;
    }
    
    *p_index = out.key_index;

    return CTC_E_NONE;
}

int32
sys_usw_pon_get_gem_port_hw_index(uint8 lchip, ctc_pon_gem_port_t* p_gem_port)
{
    int32 ret = CTC_E_NONE;
    uint32 index[3] = {0};
    char* table_name[2] = {NULL,NULL};
    char* table_str_tmm[2] = {"DsGemPortHashKey","DsL2EditGemPort"};
    char* table_str_tm[2] = {"DsGemPortHashKey","DsL2EditFlex"};
    sys_pon_gem_port_db_t gem_port;

    if (CTC_MAX_UINT32_VALUE != p_gem_port->gport)
    {
        sal_memset(&gem_port,0,sizeof(sys_pon_gem_port_db_t));
        gem_port.gport = p_gem_port->gport;
        gem_port.tunnel_value = p_gem_port->tunnel_value;
        ret = _sys_pon_get_gem_port_hw_index(lchip, &gem_port, &index[0]);
        table_name[0] = DRV_FROM_TMM(lchip)? table_str_tmm[0] : table_str_tm[0];
    }
    index[1] = sys_usw_nh_get_gem_port_l2edit_8w_outer_index(lchip, p_gem_port->logic_port);
    index[2] = p_gem_port->logic_port & 0x7;
    table_name[1] = DRV_FROM_TMM(lchip)? table_str_tmm[1] : table_str_tm[1];
    SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Detail Info\n");
    SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"---------------------------------------------------------------\n");
    SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"--%-32s :0x%-8x\n", table_name[0], index[0]);
    SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "--%-32s :0x%-8x\n", table_name[1], index[1]);
    if (DRV_FROM_TMM(lchip))
    {
        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"  --%-30s :0x%-8x\n", "sub_index", index[2]);
    }
    SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"---------------------------------------------------------------\n");
    return ret;
}

int32
sys_usw_pon_create_gem_port(uint8 lchip, ctc_pon_gem_port_t* p_gem_port)
{
    int32 ret = 0;
    uint16 lport = 0;
    sys_pon_gem_port_db_t gem_port_db;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;
    sys_pon_port_db_t* p_port_db = NULL;
    uint8 is_flooding = 0;

    /* CHECK */
    CTC_PTR_VALID_CHECK(p_gem_port);
    CTC_MAX_VALUE_CHECK(p_gem_port->logic_port,MCHIP_CAP(SYS_CAP_MAX_LOGIC_PORT));
    is_flooding = CTC_FLAG_ISSET(p_gem_port->flag, CTC_PON_GEM_PORT_FLAG_FLOODING)?1:0;
    SYS_PON_INIT_CHECK(lchip);
    if (0 == is_flooding)
    {
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_gem_port->gport, lchip, lport);
    }
    else
    {
        p_gem_port->gport = CTC_MAX_UINT32_VALUE;
    }
    
    SYS_PON_TUNNEL_VLAN_ID_CHECK(p_gem_port->tunnel_value);

    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         p_gem_port->gport);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "tunnel_value",  p_gem_port->tunnel_value);

    SYS_PON_LOCK(lchip);

    /* DB */
    if(0 == is_flooding)
    {
        p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

        if (0 == p_port_db->enable)
        {
            SYS_PON_UNLOCK(lchip);
            return CTC_E_NOT_READY;
        }
    }

    if(CTC_WB_ENABLE(lchip) && p_usw_pon_master[lchip]->gem_port_hash->count >= SYS_WB_PON_GEM_PORT_NUM)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NO_MEMORY;
    }

    sal_memset(&gem_port_db, 0, sizeof(gem_port_db));
    gem_port_db.gport = p_gem_port->gport;
    gem_port_db.tunnel_value = p_gem_port->tunnel_value;
    p_gem_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->gem_port_hash, &gem_port_db);
    if (NULL != p_gem_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_EXIST;
    }

    MALLOC_PON_POINTER(sys_pon_gem_port_db_t, p_gem_port_db);
    if (NULL == p_gem_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NO_MEMORY;
    }

    sal_memset(p_gem_port_db, 0, sizeof(sys_pon_gem_port_db_t));
    p_gem_port_db->gport = p_gem_port->gport;
    p_gem_port_db->tunnel_value = p_gem_port->tunnel_value;
    p_gem_port_db->pass_through_en = p_gem_port->pass_through_en?1:0;
    p_gem_port_db->igs_policer_id = p_gem_port->igs_policer_id;
    p_gem_port_db->logic_port = p_gem_port->logic_port;
    p_gem_port_db->mac_security = p_gem_port->limit_action;
    CTC_ERROR_GOTO(sys_usw_nh_add_gem_port_l2edit_8w_outer(lchip, p_gem_port_db->logic_port, p_gem_port_db->tunnel_value), ret, free_meomory);
    
    /*Create gem port sevice*/
    if(0 == is_flooding)
    {
        p_gem_port_db->egs_service_id = p_gem_port->egs_service_id;
        CTC_ERROR_GOTO(_sys_pon_add_gem_port_hw(lchip, p_gem_port_db), ret,  roll_back_1);
        if(p_gem_port_db->egs_service_id)
        {
            CTC_ERROR_GOTO(sys_usw_qos_bind_service_logic_dstport(lchip, p_gem_port_db->egs_service_id, p_gem_port_db->logic_port, p_gem_port_db->gport, 0), ret, roll_back_2);
        }
    }
    else
    {
        p_gem_port_db->is_flooding = 1;
        p_gem_port_db->egs_service_id = p_gem_port->logic_port;
        CTC_ERROR_GOTO(sys_usw_nh_xgpon_flooding_en(lchip, p_gem_port_db->logic_port, TRUE), ret, free_meomory);
    }

    /* DB & STATS */
    if (NULL == ctc_hash_insert(p_usw_pon_master[lchip]->gem_port_hash, p_gem_port_db))
    {
        ret = CTC_E_NO_MEMORY;
        goto roll_back_3;
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_GEM_PORT, 1);

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;

   /*-----------------------------------------------------------
   *** rool back
   -----------------------------------------------------------*/
roll_back_3:
    if(p_gem_port_db->egs_service_id)
    {
        sys_usw_qos_unbind_service_logic_dstport(lchip, p_gem_port_db->egs_service_id, p_gem_port_db->logic_port, p_gem_port_db->gport);
    }
roll_back_2:
    _sys_pon_remove_gem_port_hw(lchip, p_gem_port_db);
roll_back_1:
    sys_usw_nh_remove_gem_port_l2edit_8w_outer(lchip, p_gem_port_db->logic_port);

free_meomory:
    mem_free(p_gem_port_db);
    p_gem_port_db = NULL;
    SYS_PON_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_pon_destroy_gem_port(uint8 lchip, ctc_pon_gem_port_t* p_gem_port)
{
    uint16 lport = 0;
    sys_pon_gem_port_db_t gem_port_db;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;
    sys_pon_port_db_t* p_port_db = NULL;
    uint8 is_flooding = 0;

    /* CHECK */
    CTC_PTR_VALID_CHECK(p_gem_port);
    is_flooding = CTC_FLAG_ISSET(p_gem_port->flag, CTC_PON_GEM_PORT_FLAG_FLOODING)?1:0;
    SYS_PON_INIT_CHECK(lchip);
    if (0 == is_flooding)
    {
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_gem_port->gport, lchip, lport);
    }
    else
    {
        p_gem_port->gport = CTC_MAX_UINT32_VALUE;
    }
    SYS_PON_TUNNEL_VLAN_ID_CHECK(p_gem_port->tunnel_value);

    /* Debug */
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport", p_gem_port->gport);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "tunnel_value", p_gem_port->tunnel_value);

    SYS_PON_LOCK(lchip);

    /* DB */
    if(0 == is_flooding)
    {
        p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

        if (0 == p_port_db->enable)
        {
            SYS_PON_UNLOCK(lchip);
            return CTC_E_NOT_READY;
        }
    }
    sal_memset(&gem_port_db, 0, sizeof(gem_port_db));
    gem_port_db.gport = p_gem_port->gport;
    gem_port_db.tunnel_value = p_gem_port->tunnel_value;
    p_gem_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->gem_port_hash, &gem_port_db);
    if (NULL == p_gem_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    if (p_gem_port_db->ref_cnt)
    {
        SYS_PON_UNLOCK(lchip);
        return  CTC_E_IN_USE;
    }

    /*Create gem port sevice*/
    if(0 == is_flooding)
    {
        SYS_PON_ERROR_RETURN_UNLOCK(_sys_pon_remove_gem_port_hw(lchip, p_gem_port_db));
        if(p_gem_port_db->egs_service_id)
        {
            SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_qos_unbind_service_logic_dstport(lchip, p_gem_port_db->egs_service_id, p_gem_port_db->logic_port, p_gem_port_db->gport));
        }
    }
    else
    {
        sys_usw_nh_xgpon_flooding_en(lchip, p_gem_port_db->logic_port, FALSE);
    }

    SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_nh_remove_gem_port_l2edit_8w_outer(lchip, p_gem_port_db->logic_port));

    ctc_hash_remove(p_usw_pon_master[lchip]->gem_port_hash, p_gem_port_db);

    mem_free(p_gem_port_db);
    p_gem_port_db = NULL;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_GEM_PORT, 1);

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_pon_update_gem_port(uint8 lchip, ctc_pon_gem_port_t* p_gem_port)
{
    uint16 lport = 0;
    sys_pon_gem_port_db_t gem_port_db;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;
    sys_pon_port_db_t* p_port_db = NULL;
    uint8 is_flooding = 0;

    /* CHECK */
    CTC_PTR_VALID_CHECK(p_gem_port);
    is_flooding = CTC_FLAG_ISSET(p_gem_port->flag, CTC_PON_GEM_PORT_FLAG_FLOODING)?1:0;
    SYS_PON_INIT_CHECK(lchip);
    if (0 == is_flooding)
    {
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_gem_port->gport, lchip, lport);
    }
    else
    {
        p_gem_port->gport = CTC_MAX_UINT32_VALUE;
    }
    SYS_PON_TUNNEL_VLAN_ID_CHECK(p_gem_port->tunnel_value);

    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "port", p_gem_port->gport);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "tunnel_value", p_gem_port->tunnel_value);

    SYS_PON_LOCK(lchip);

    /* DB */
    if(0 == is_flooding)
    {
        p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

        if (0 == p_port_db->enable)
        {
            SYS_PON_UNLOCK(lchip);
            return CTC_E_NOT_READY;
        }
    }
    sal_memset(&gem_port_db, 0, sizeof(gem_port_db));
    gem_port_db.gport = p_gem_port->gport;
    gem_port_db.tunnel_value = p_gem_port->tunnel_value;
    p_gem_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->gem_port_hash, &gem_port_db);
    if (NULL == p_gem_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    if(0 == is_flooding)
    {
        if (CTC_FLAG_ISSET(p_gem_port->flag, CTC_PON_GEM_PORT_FLAG_PASS_THROUGH_EN) ||
            CTC_FLAG_ISSET(p_gem_port->flag, CTC_PON_GEM_PORT_FLAG_MAC_LIMIT))
        {
            if (CTC_FLAG_ISSET(p_gem_port->flag, CTC_PON_GEM_PORT_FLAG_PASS_THROUGH_EN))
            {
                p_gem_port_db->pass_through_en = p_gem_port->pass_through_en;
            }

            if (CTC_FLAG_ISSET(p_gem_port->flag, CTC_PON_GEM_PORT_FLAG_MAC_LIMIT))
            {
                p_gem_port_db->mac_security = p_gem_port->limit_action;
            }

            SYS_PON_ERROR_RETURN_UNLOCK(_sys_pon_add_gem_port_hw(lchip, p_gem_port_db));
        }


        if (p_gem_port->egs_service_id != p_gem_port_db->egs_service_id)
        {
            if(p_gem_port->egs_service_id)
            {
                SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_qos_bind_service_logic_dstport(lchip, p_gem_port->egs_service_id, p_gem_port_db->logic_port, p_gem_port_db->gport, 0));
            }
            SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_qos_unbind_service_logic_dstport(lchip, p_gem_port_db->egs_service_id, p_gem_port_db->logic_port, p_gem_port_db->gport));
            p_gem_port_db->egs_service_id = p_gem_port->egs_service_id;
        }
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_GEM_PORT, 1);
    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;
}



#define ___UNI_VLAN_PORT___


int32
sys_usw_pon_get_gem_port(uint8 lchip, ctc_pon_gem_port_t* p_gem_port)
{
    sys_pon_gem_port_db_t gem_port_db;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;

    /* CHECK */
    CTC_PTR_VALID_CHECK(p_gem_port);
    SYS_PON_INIT_CHECK(lchip);
    SYS_PON_TUNNEL_VLAN_ID_CHECK(p_gem_port->tunnel_value);
    if (CTC_FLAG_ISSET(p_gem_port->flag, CTC_PON_GEM_PORT_FLAG_FLOODING))
    {
        p_gem_port->gport = CTC_MAX_UINT32_VALUE;
    }
    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "port", p_gem_port->gport);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "tunnel_value", p_gem_port->tunnel_value);

    SYS_PON_LOCK(lchip);

    /* DB */
    sal_memset(&gem_port_db, 0, sizeof(gem_port_db));
    gem_port_db.gport = p_gem_port->gport;
    gem_port_db.tunnel_value = p_gem_port->tunnel_value;
    p_gem_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->gem_port_hash, &gem_port_db);
    if (NULL == p_gem_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    p_gem_port->logic_port = p_gem_port_db->logic_port;
    p_gem_port->igs_policer_id = p_gem_port_db->igs_policer_id;
    p_gem_port->pass_through_en = p_gem_port_db->pass_through_en;
    p_gem_port->limit_action = p_gem_port_db->mac_security;
    p_gem_port->egs_service_id = p_gem_port_db->egs_service_id;

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;
}


/*Vlan Port*/
void _sys_usw_pon_vlan_port_mapping_pkt_vlan(uint8 lchip, sys_pon_vlan_port_db_t* p_vlan_port_db, ctc_scl_vlan_edit_t *p_vlan_edit)
{
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "svid_new", p_vlan_edit->svid_new);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "cvid_new", p_vlan_edit->svid_new);
    if (CTC_VLAN_TAG_OP_ADD == p_vlan_edit->stag_op)
        {
            if(CTC_VLAN_TAG_OP_ADD == p_vlan_edit->ctag_op)
            {
                p_vlan_port_db->pkt_svlan = p_vlan_edit->svid_new;
                p_vlan_port_db->pkt_cvlan = p_vlan_edit->cvid_new;
            }
            else
            {
                p_vlan_port_db->pkt_svlan = p_vlan_edit->svid_new;
                if (p_vlan_port_db->match_svlan_end)
                {
                    p_vlan_port_db->pkt_cvlan = p_vlan_port_db->match_svlan_end;
                }
                else
                {
                    p_vlan_port_db->pkt_cvlan = p_vlan_port_db->match_svlan;
                }
            }
        }
        else if(CTC_VLAN_TAG_OP_REP == p_vlan_edit->stag_op)
        {
            if ((CTC_VLAN_TAG_OP_ADD == p_vlan_edit->ctag_op) || \
                (CTC_VLAN_TAG_OP_REP == p_vlan_edit->ctag_op))
            {
                p_vlan_port_db->pkt_svlan = p_vlan_edit->svid_new;
                p_vlan_port_db->pkt_cvlan = p_vlan_edit->cvid_new;
            }
            else
            {
                p_vlan_port_db->pkt_svlan = p_vlan_edit->svid_new;
                p_vlan_port_db->pkt_cvlan = p_vlan_port_db->match_cvlan;
            }
        }
        else if(CTC_VLAN_TAG_OP_NONE == p_vlan_edit->stag_op)
        {
            if ((CTC_VLAN_TAG_OP_ADD == p_vlan_edit->ctag_op) || \
                (CTC_VLAN_TAG_OP_REP == p_vlan_edit->ctag_op))
            {
                p_vlan_port_db->pkt_svlan = p_vlan_port_db->match_svlan;
                p_vlan_port_db->pkt_cvlan = p_vlan_edit->cvid_new;
            }
            else
            {
                p_vlan_port_db->pkt_svlan = p_vlan_port_db->match_svlan;
                p_vlan_port_db->pkt_cvlan = p_vlan_port_db->match_cvlan;
            }
        }
    return;
}


STATIC int32
_sys_usw_pon_vlan_port_match_vlan(uint8 lchip,
                                   ctc_pon_vlan_port_t* p_vlan_port,
                                   sys_pon_vlan_port_db_t* p_vlan_port_db)
{
    uint8 i = 0;

    for (i = 0; i < p_vlan_port->fields_num; i++)
    {
        switch(p_vlan_port->match_fields[i].type)
        {
           case CTC_FIELD_KEY_SVLAN_ID:
            p_vlan_port_db->match_svlan = p_vlan_port->match_fields[i].data;
            break;

           case CTC_FIELD_KEY_CVLAN_ID:
            p_vlan_port_db->match_cvlan = p_vlan_port->match_fields[i].data;
            break;
           
           case CTC_FIELD_KEY_STAG_COS:
            p_vlan_port_db->match_scos = p_vlan_port->match_fields[i].data;
            p_vlan_port_db->match_scos_valid = 1;
            break;

           case CTC_FIELD_KEY_SVLAN_RANGE:
            p_vlan_port_db->match_svlan = p_vlan_port->match_fields[i].data;
            p_vlan_port_db->match_svlan_end = p_vlan_port->match_fields[i].mask;
            break;

           case CTC_FIELD_KEY_CVLAN_RANGE:
            p_vlan_port_db->match_cvlan = p_vlan_port->match_fields[i].data;
            p_vlan_port_db->match_cvlan_end = p_vlan_port->match_fields[i].mask;
            break;
            
            case CTC_FIELD_KEY_PORT:
            p_vlan_port_db->acl_logic_port = p_vlan_port->match_fields[i].data;
            break;
            
           default:
            break;
        }
    }

    _sys_usw_pon_vlan_port_mapping_pkt_vlan(lchip, p_vlan_port_db, &p_vlan_port->igs_vlan_action);

    if(p_vlan_port_db->match_scos_valid && p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN)
    {
        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [PON] Invalid config , line:%d\n", __LINE__);
        return CTC_E_INVALID_CONFIG;
    }

    return CTC_E_NONE;
}
                                   

STATIC int32
_sys_usw_pon_vlan_port_vlan_mapping(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port,
                               ctc_vlan_mapping_t* p_vlan_mapping, ctc_scl_vlan_edit_t* p_vlan_edit)
{
    SYS_PON_INIT_CHECK(lchip);

    /*SVLAN op*/
    switch(p_vlan_port->igs_vlan_action.stag_op)
    {
        case CTC_VLAN_TAG_OP_ADD:
            CTC_VLAN_RANGE_CHECK(p_vlan_port->igs_vlan_action.svid_new);
            if (p_vlan_mapping)
            {
                CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_SVID);
                p_vlan_mapping->stag_op = CTC_VLAN_TAG_OP_ADD;
                p_vlan_mapping->svid_sl = CTC_VLAN_TAG_SL_NEW;
                p_vlan_mapping->new_svid = p_vlan_port->igs_vlan_action.svid_new;
            }
            else
            {
                p_vlan_edit->stag_op = CTC_VLAN_TAG_OP_ADD;
                p_vlan_edit->svid_sl = CTC_VLAN_TAG_SL_NEW;
                p_vlan_edit->svid_new = p_vlan_port->igs_vlan_action.svid_new;
            }
            break;

        case CTC_VLAN_TAG_OP_REP:
            CTC_VLAN_RANGE_CHECK(p_vlan_port->igs_vlan_action.svid_new);
            if (p_vlan_mapping)
            {
                CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_SVID);
                p_vlan_mapping->stag_op = CTC_VLAN_TAG_OP_REP;
                p_vlan_mapping->svid_sl = CTC_VLAN_TAG_SL_NEW;
                p_vlan_mapping->new_svid = p_vlan_port->igs_vlan_action.svid_new;
            }
            else
            {
                p_vlan_edit->stag_op = CTC_VLAN_TAG_OP_REP;
                p_vlan_edit->svid_sl = CTC_VLAN_TAG_SL_NEW;
                p_vlan_edit->svid_new = p_vlan_port->igs_vlan_action.svid_new;
            }
            break;

        case CTC_VLAN_TAG_OP_DEL:
            if (p_vlan_mapping)
            {
                CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_SVID);
                p_vlan_mapping->stag_op = CTC_VLAN_TAG_OP_DEL;
            }
            else
            {
                p_vlan_edit->stag_op = CTC_VLAN_TAG_OP_DEL;
            }
            return CTC_E_INVALID_PARAM;
            break;

         case CTC_VLAN_TAG_OP_NONE:
         case CTC_VLAN_TAG_OP_VALID:
            if (p_vlan_mapping)
            {
                CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_SVID);
                p_vlan_mapping->stag_op = CTC_VLAN_TAG_OP_VALID;
            }
            else
            {
                p_vlan_edit->stag_op = CTC_VLAN_TAG_OP_VALID;
            }
            break;

        default:
            return CTC_E_INVALID_PARAM;
    }

    switch(p_vlan_port->igs_vlan_action.ctag_op)
    {
        case CTC_VLAN_TAG_OP_ADD:
            CTC_VLAN_RANGE_CHECK(p_vlan_port->igs_vlan_action.cvid_new);
            if (p_vlan_mapping)
            {
                CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_CVID);
                p_vlan_mapping->ctag_op = CTC_VLAN_TAG_OP_ADD;
                p_vlan_mapping->cvid_sl = CTC_VLAN_TAG_SL_NEW;
                p_vlan_mapping->new_cvid = p_vlan_port->igs_vlan_action.cvid_new;
            }
            else
            {
                p_vlan_edit->ctag_op = CTC_VLAN_TAG_OP_ADD;
                p_vlan_edit->cvid_sl = CTC_VLAN_TAG_SL_NEW;
                p_vlan_edit->cvid_new = p_vlan_port->igs_vlan_action.cvid_new;
            }
            break;

        case CTC_VLAN_TAG_OP_REP:
            CTC_VLAN_RANGE_CHECK(p_vlan_port->igs_vlan_action.cvid_new);
            if (p_vlan_mapping)
            {
                CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_CVID);
                p_vlan_mapping->ctag_op = CTC_VLAN_TAG_OP_REP;
                p_vlan_mapping->cvid_sl = CTC_VLAN_TAG_SL_NEW;
                p_vlan_mapping->new_cvid = p_vlan_port->igs_vlan_action.cvid_new;
            }
            else
            {
                p_vlan_edit->ctag_op = CTC_VLAN_TAG_OP_REP;
                p_vlan_edit->cvid_sl = CTC_VLAN_TAG_SL_NEW;
                p_vlan_edit->cvid_new = p_vlan_port->igs_vlan_action.cvid_new;
            }
            break;

        case CTC_VLAN_TAG_OP_DEL:
            if (p_vlan_mapping)
            {
                CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_CVID);
                p_vlan_mapping->ctag_op = CTC_VLAN_TAG_OP_DEL;
            }
            else
            {
                p_vlan_edit->ctag_op = CTC_VLAN_TAG_OP_DEL;
            }
            return CTC_E_INVALID_PARAM;
            break;


         case CTC_VLAN_TAG_OP_NONE:
         case CTC_VLAN_TAG_OP_VALID:
            if (p_vlan_mapping)
            {
                CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_CVID);
                p_vlan_mapping->ctag_op = CTC_VLAN_TAG_OP_VALID;
            }
            else
            {
                p_vlan_edit->ctag_op = CTC_VLAN_TAG_OP_VALID;
            }
            break;

        default:
            return CTC_E_INVALID_PARAM;
    }

    if (p_vlan_mapping)
    {
        p_vlan_mapping->scos_sl = p_vlan_port->igs_vlan_action.scos_sl;
        p_vlan_mapping->new_scos = p_vlan_port->igs_vlan_action.scos_new;

        if (CTC_VLAN_TAG_SL_AS_PARSE != p_vlan_port->igs_vlan_action.scos_sl)
        {
            CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_SCOS);
        }

        p_vlan_mapping->ccos_sl = p_vlan_port->igs_vlan_action.ccos_sl;
        p_vlan_mapping->new_ccos = p_vlan_port->igs_vlan_action.ccos_new;

        if (CTC_VLAN_TAG_SL_AS_PARSE != p_vlan_port->igs_vlan_action.ccos_sl)
        {
            CTC_SET_FLAG(p_vlan_mapping->action, CTC_VLAN_MAPPING_OUTPUT_CCOS);
        }
    }
    else
    {
        p_vlan_edit->scos_sl = p_vlan_port->igs_vlan_action.scos_sl;
        p_vlan_edit->scos_new = p_vlan_port->igs_vlan_action.scos_new;

        p_vlan_edit->ccos_sl = p_vlan_port->igs_vlan_action.ccos_sl;
        p_vlan_edit->ccos_new = p_vlan_port->igs_vlan_action.ccos_new;

    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_pon_vlan_port_nh_xlate_mapping(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port,
                               ctc_vlan_egress_edit_info_t* p_xlate)
{
    SYS_PON_INIT_CHECK(lchip);

    /* SVLAN op */
    switch(p_vlan_port->egs_vlan_action.stag_op)
    {
        case CTC_VLAN_TAG_OP_DEL:
            p_xlate->svlan_edit_type = CTC_VLAN_EGRESS_EDIT_STRIP_VLAN;
            break;

        case CTC_VLAN_TAG_OP_REP:
            p_xlate->svlan_edit_type = CTC_VLAN_EGRESS_EDIT_REPLACE_VLAN;
            p_xlate->output_svid = p_vlan_port->egs_vlan_action.svid_new;
            CTC_SET_FLAG(p_xlate->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID);
            break;

         case CTC_VLAN_TAG_OP_NONE:
            p_xlate->svlan_edit_type = CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE;
            break;

        case CTC_VLAN_TAG_OP_ADD:
            p_xlate->svlan_edit_type = CTC_VLAN_EGRESS_EDIT_INSERT_VLAN;
            p_xlate->output_svid = p_vlan_port->egs_vlan_action.svid_new;
            CTC_SET_FLAG(p_xlate->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID);
            break;

        default:
            return CTC_E_INVALID_PARAM;
    }

    /* CVLAN op */
    switch(p_vlan_port->egs_vlan_action.ctag_op)
    {
        case CTC_VLAN_TAG_OP_DEL:
            p_xlate->cvlan_edit_type = CTC_VLAN_EGRESS_EDIT_STRIP_VLAN;
            break;

        case CTC_VLAN_TAG_OP_REP:
            p_xlate->cvlan_edit_type = CTC_VLAN_EGRESS_EDIT_REPLACE_VLAN;
            p_xlate->output_cvid = p_vlan_port->egs_vlan_action.cvid_new;
            CTC_SET_FLAG(p_xlate->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID);
            break;

        case CTC_VLAN_TAG_OP_NONE:
            p_xlate->cvlan_edit_type = CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE;
            break;

        case CTC_VLAN_TAG_OP_ADD:
            p_xlate->cvlan_edit_type = CTC_VLAN_EGRESS_EDIT_INSERT_VLAN;
            p_xlate->output_cvid = p_vlan_port->egs_vlan_action.cvid_new;
            CTC_SET_FLAG(p_xlate->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID);
            break;


        default:
            return CTC_E_INVALID_PARAM;
    }

    /* SCOS op */
    if (p_vlan_port->egs_vlan_action.scos_sl == CTC_VLAN_TAG_SL_NEW)
    {
        CTC_SET_FLAG(p_xlate->edit_flag, CTC_VLAN_EGRESS_EDIT_REPLACE_SVLAN_COS);
        p_xlate->stag_cos = p_vlan_port->egs_vlan_action.scos_new;
    }


    /* CCOS op */
    if (CTC_VLAN_TAG_SL_AS_PARSE != p_vlan_port->egs_vlan_action.ccos_sl)
    {
        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [PON] Invalid para , line:%d\n", __LINE__);
        return CTC_E_INVALID_PARAM;
    }


    return CTC_E_NONE;
}

#if 0
STATIC int32
_sys_usw_pon_vlan_port_nh_xlate_mapping2(uint8 lchip, ctc_scl_vlan_edit_t* p_vlan_port, ctc_vlan_egress_edit_info_t* p_xlate)
{
    SYS_PON_INIT_CHECK(lchip);

    switch(p_xlate->svlan_edit_type)
    {
        case CTC_VLAN_EGRESS_EDIT_STRIP_VLAN:
            p_vlan_port->stag_op = CTC_VLAN_TAG_OP_DEL;
            break;
        case CTC_VLAN_EGRESS_EDIT_REPLACE_VLAN:
            p_vlan_port->stag_op = CTC_VLAN_TAG_OP_REP;
            p_vlan_port->svid_new = p_xlate->output_svid;
            break;
        case CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE:
            p_vlan_port->stag_op = CTC_VLAN_TAG_OP_NONE;
            break;
        case CTC_VLAN_EGRESS_EDIT_INSERT_VLAN:
            p_vlan_port->stag_op = CTC_VLAN_TAG_OP_ADD;
            p_vlan_port->svid_new = p_xlate->output_svid;
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }
    
    switch(p_xlate->cvlan_edit_type)
    {
        case CTC_VLAN_EGRESS_EDIT_STRIP_VLAN:
            p_vlan_port->ctag_op = CTC_VLAN_TAG_OP_DEL;
            break;
        case CTC_VLAN_EGRESS_EDIT_REPLACE_VLAN:
            p_vlan_port->ctag_op = CTC_VLAN_TAG_OP_REP;
            p_vlan_port->cvid_new = p_xlate->output_cvid;
            break;
        case CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE:
            p_vlan_port->ctag_op = CTC_VLAN_TAG_OP_NONE;
            break;
        case CTC_VLAN_EGRESS_EDIT_INSERT_VLAN:
            p_vlan_port->ctag_op = CTC_VLAN_TAG_OP_ADD;
            p_vlan_port->cvid_new = p_xlate->output_cvid;
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    /* SCOS op */
    if (CTC_FLAG_ISSET(p_xlate->edit_flag, CTC_VLAN_EGRESS_EDIT_REPLACE_SVLAN_COS))
    {
        p_vlan_port->scos_new = p_xlate->stag_cos;
        p_vlan_port->scos_sl = CTC_VLAN_TAG_SL_NEW;
    }

    p_vlan_port->ccos_sl = CTC_VLAN_TAG_SL_AS_PARSE;

    return CTC_E_NONE;
}
#endif

int32
_sys_usw_pon_vlan_port_downlink_scl_add(uint8 lchip,
                                    ctc_pon_vlan_port_t* p_vlan_port,
                                    sys_pon_vlan_port_db_t* p_vlan_port_db,
                                    sys_pon_port_db_t* p_port_db)
{
    int32 ret = 0;
    uint32 entry_id = 0;
    uint32 gid = 0;
    ctc_field_key_t key_field;
    ctc_field_port_t p_port;
    ctc_scl_field_action_t action_field;
    ctc_scl_vlan_edit_t vlan_edit;
    ctc_vlan_range_info_t range_info;
    ctc_vlan_range_t vlan_range;
    ctc_scl_entry_t  scl_entry;

    sal_memset(&range_info, 0, sizeof(range_info));
    sal_memset(&vlan_range, 0, sizeof(vlan_range));

    if (p_vlan_port_db->match_svlan_end)
    {
        CTC_ERROR_RETURN(_sys_usw_pon_vlan_range_group_en(lchip, p_vlan_port->gport, TRUE));
        range_info.direction = CTC_EGRESS;
        range_info.vrange_grpid = p_port_db->vlan_range_grp;
        vlan_range.vlan_start = p_vlan_port_db->match_svlan;
        vlan_range.vlan_end   = p_vlan_port_db->match_svlan_end;
        SYS_PON_DBG_INFO("vlan range group id: %d, vlan start: %d, vlan end: %d\n", range_info.vrange_grpid, vlan_range.vlan_start,vlan_range.vlan_end);
        CTC_ERROR_GOTO(sys_usw_vlan_add_vlan_range_member(lchip, &range_info, &vlan_range), ret, roll_back_0);
    }

    sal_memset(&scl_entry, 0, sizeof(ctc_scl_entry_t));
    entry_id = ENCODE_SCL_VLAN_ENTRY_ID(p_vlan_port_db->vlan_port_id);
    scl_entry.entry_id = entry_id;
    scl_entry.key_type = CTC_SCL_KEY_HASH_PORT_2VLAN;
    scl_entry.action_type = CTC_SCL_ACTION_EGRESS;
    scl_entry.mode = 1;
    gid = CTC_SCL_GROUP_ID_HASH_PORT_2VLAN;
    CTC_ERROR_GOTO(sys_usw_scl_add_entry(lchip, gid, &scl_entry, 0), ret, roll_back_1);

    sal_memset(&key_field, 0, sizeof(key_field));
    sal_memset(&p_port, 0, sizeof(p_port));
    p_port.type = CTC_FIELD_PORT_TYPE_GPORT;
    p_port.gport = p_vlan_port->gport;
    key_field.ext_data = &p_port;
    key_field.type = CTC_FIELD_KEY_DST_GPORT;
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &key_field), ret, roll_back_2);
    sal_memset(&key_field, 0, sizeof(key_field));
    key_field.type = CTC_FIELD_KEY_SVLAN_ID;
    key_field.data = p_vlan_port_db->pkt_svlan;
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &key_field), ret, roll_back_2);
    key_field.type = CTC_FIELD_KEY_CVLAN_ID;
    if (p_vlan_port_db->match_svlan_end)
    {
        key_field.data = p_vlan_port_db->match_svlan_end;
    }
    else
    {
        key_field.data = p_vlan_port_db->pkt_cvlan;
    }
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &key_field), ret, roll_back_2);

    key_field.type = CTC_FIELD_KEY_HASH_VALID;
    key_field.data = 1;
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &key_field), ret, roll_back_2);
    sal_memset(&action_field, 0, sizeof(action_field));
    sal_memcpy(&vlan_edit, &p_vlan_port->egs_vlan_action, sizeof(ctc_scl_vlan_edit_t));
    action_field.type = CTC_SCL_FIELD_ACTION_TYPE_VLAN_EDIT;
    action_field.ext_data = &vlan_edit;
    CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &action_field), ret, roll_back_2);

    CTC_ERROR_GOTO(sys_usw_scl_install_entry(lchip, entry_id, 0), ret, roll_back_2);

    return CTC_E_NONE;

roll_back_2:
    sys_usw_scl_remove_entry(lchip, entry_id, 0);

roll_back_1:
    if (p_vlan_port_db->match_svlan_end)
    {
        sys_usw_vlan_remove_vlan_range_member(lchip, &range_info, &vlan_range);
    }

roll_back_0:
    if (p_vlan_port_db->match_svlan_end)
    {
        _sys_usw_pon_vlan_range_group_en(lchip, p_vlan_port->gport, FALSE);
    }
    return ret;
}


int32
_sys_usw_pon_vlan_port_downlink_scl_remove(uint8 lchip,
                                      sys_pon_vlan_port_db_t* p_vlan_port_db,
                                      sys_pon_port_db_t* p_port_db)
{
    ctc_vlan_range_info_t range_info;
    ctc_vlan_range_t vlan_range;
    uint32 entry_id = 0;

    sal_memset(&range_info, 0, sizeof(range_info));
    sal_memset(&vlan_range, 0, sizeof(vlan_range));

    entry_id = ENCODE_SCL_VLAN_ENTRY_ID(p_vlan_port_db->vlan_port_id);
    sys_usw_scl_uninstall_entry(lchip, entry_id, 0);
    sys_usw_scl_remove_entry(lchip, entry_id, 0);

    if (p_vlan_port_db->match_svlan_end)
    {
        range_info.direction = CTC_EGRESS;
        range_info.vrange_grpid = p_port_db->vlan_range_grp;
        vlan_range.vlan_start = p_vlan_port_db->match_svlan;
        vlan_range.vlan_end   = p_vlan_port_db->match_svlan_end;
        SYS_PON_DBG_INFO("vlan range group id: %d, vlan start: %d, vlan end: %d\n", range_info.vrange_grpid, vlan_range.vlan_start,vlan_range.vlan_end);
        sys_usw_vlan_remove_vlan_range_member(lchip, &range_info, &vlan_range);
        _sys_usw_pon_vlan_range_group_en(lchip, p_vlan_port_db->gport, FALSE);
    }

    return CTC_E_NONE;
}

int32
_sys_usw_pon_vlan_port_downlink_nexthop_add(uint8 lchip,
                                        ctc_pon_vlan_port_t* p_vlan_port,
                                        sys_pon_vlan_port_db_t* p_vlan_port_db,
                                        sys_pon_port_db_t* p_port_db)
{
    ctc_vlan_edit_nh_param_t vlan_xlate_nh;
    ctc_vlan_egress_edit_info_t* p_vlan_edit_info = NULL;

    /* Create xlate nh */
    sal_memset(&vlan_xlate_nh, 0, sizeof(vlan_xlate_nh));
    if(!p_vlan_port_db->xlate_nhid)
    {
        return CTC_E_NONE;
    }
    vlan_xlate_nh.gport_or_aps_bridge_id = p_vlan_port_db->gport;
    CTC_ERROR_RETURN(_sys_usw_pon_vlan_port_nh_xlate_mapping(lchip, p_vlan_port, &vlan_xlate_nh.vlan_edit_info));
    SYS_PON_DBG_INFO("nh xlate nhid: %u\n", p_vlan_port_db->xlate_nhid);
    p_vlan_edit_info = &(vlan_xlate_nh.vlan_edit_info);
    CTC_ERROR_RETURN(sys_usw_egress_vlan_edit_nh_create(lchip, p_vlan_port_db->xlate_nhid, p_vlan_port_db->gport, p_vlan_edit_info, p_vlan_port->dsnh_offset, &vlan_xlate_nh));
    p_vlan_port_db->egs_vlan_mapping_en = 0;

    return CTC_E_NONE;

}

int32
_sys_usw_pon_vlan_port_downlink_nexthop_remove(uint8 lchip,
                                      sys_pon_vlan_port_db_t* p_vlan_port_db,
                                      sys_pon_port_db_t* p_port_db)
{
    if(!p_vlan_port_db->xlate_nhid)
    {
        return CTC_E_NONE;
    }
    CTC_ERROR_RETURN(sys_usw_egress_vlan_edit_nh_delete(lchip, p_vlan_port_db->xlate_nhid));
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_pon_vlan_port_add_downlink_flex(uint8 lchip, sys_pon_port_db_t* p_port_db, 
                                            ctc_pon_vlan_port_t* p_vlan_port)
{
    int32 ret = 0;
    uint8 i = 0;
    uint8 tcam_type = 0;
    uint8 scl_id = 0;
    uint32 entry_id = 0;
    uint32 group_id = 0;
    ctc_field_key_t field_key;
    ctc_field_port_t field_port;
    ctc_field_port_t field_port_mask;
    ctc_scl_field_action_t field_action;
    ctc_port_scl_property_t scl_prop;
    ctc_scl_entry_t scl_entry;

    scl_id = CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_SCL_ID)?p_vlan_port->scl_id : 2;
    group_id =  (scl_id == 2 ) ? CTC_SCL_GROUP_ID_TCAM2 : CTC_SCL_GROUP_ID_TCAM3;
    entry_id = ENCODE_SCL_VLAN_ENTRY_ID(p_vlan_port->vlan_port_id);
    sal_memset(&scl_entry, 0, sizeof(ctc_scl_entry_t));
    if (p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_FLEX_MAC)
    {
        scl_entry.key_type = CTC_SCL_KEY_TCAM_MAC;
        tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_MAC;
    }
    else if(p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_FLEX_IPV4)
    {
        scl_entry.key_type = CTC_SCL_KEY_TCAM_IPV4;
        tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_IP;
    }
    else if(p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_FLEX_IPV6)
    {
        scl_entry.key_type = CTC_SCL_KEY_TCAM_IPV6;
        tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_IP;
    }

    scl_entry.mode = 1;
    scl_entry.action_type =  CTC_SCL_ACTION_INGRESS;
    scl_entry.entry_id = entry_id;
    if(DRV_FROM_TMM(lchip))
    {
        scl_entry.priority = CTC_PON_FLEX_EPRI;
        scl_entry.priority_valid  =1;
    }
    CTC_ERROR_RETURN(sys_usw_scl_add_entry(lchip, group_id, &scl_entry, 0));

    sal_memset(&field_key, 0, sizeof(ctc_field_key_t));
    sal_memset(&field_port, 0, sizeof(ctc_field_port_t));
    sal_memset(&field_port_mask, 0xFF, sizeof(ctc_field_port_t));
    field_key.type = CTC_FIELD_KEY_PORT;
    field_port.logic_port = p_port_db->logic_port;
    field_port.type = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
    field_key.ext_data = &field_port;
    field_key.ext_mask = &field_port_mask;
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &field_key), ret, roll_back_0);

    for (i = 0; i < p_vlan_port->fields_num; i++)
    {
        CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &p_vlan_port->match_fields[i]), ret, roll_back_0);
    }

    field_action.type = CTC_SCL_FIELD_ACTION_TYPE_FID;
    field_action.data0 = p_vlan_port->fid;
    CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, roll_back_0);

    CTC_ERROR_GOTO(sys_usw_scl_install_entry(lchip, entry_id, 0), ret, roll_back_0);

    /** Enable scl lookup double vlan for onu and pon qinq */
    sal_memset(&scl_prop, 0, sizeof(scl_prop));
    sys_usw_port_get_scl_property(lchip, p_vlan_port->gport, &scl_prop);
    if (tcam_type!=scl_prop.tcam_type && CTC_PORT_IGS_SCL_TCAM_TYPE_RESOLVE_CONFLICT!=scl_prop.tcam_type)
    {
        SYS_PON_DBG_ERROR("Tcam type must keep the same when update!\n");
        ret = CTC_E_INVALID_PARAM;
        goto roll_back_1;
    }

    if 
( (0==p_port_db->flex_pon_cnt && scl_id == 2) || 
         (0==p_port_db->flex_onu_cnt && scl_id == 3) )
    {
        sal_memset(&scl_prop, 0, sizeof(scl_prop));
        scl_prop.scl_id = scl_id;
        scl_prop.direction = CTC_INGRESS;
        scl_prop.hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
        scl_prop.use_logic_port_en = 1;
        scl_prop.tcam_type = tcam_type;
        scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
        CTC_ERROR_GOTO(sys_usw_port_set_scl_property(lchip, p_vlan_port->gport, &scl_prop), ret, roll_back_1);
    }
    (scl_id == 2) ? p_port_db->flex_pon_cnt++ : p_port_db->flex_onu_cnt++ ;
    SYS_PON_DBG_INFO("scl 2 flex pon cnt: %d, scl 3 flex pon cnt: %d\n", p_port_db->flex_pon_cnt, p_port_db->flex_onu_cnt);
    p_vlan_port->scl_eid = entry_id;

    return CTC_E_NONE;

roll_back_1:
    sys_usw_scl_uninstall_entry(lchip, entry_id, 0);
roll_back_0:
    sys_usw_scl_remove_entry(lchip, entry_id, 0);

    return ret;
}

STATIC int32 
_sys_usw_pon_vlan_port_remove_downlink_flex(uint8 lchip, sys_pon_port_db_t* p_port_db, 
                                             sys_pon_vlan_port_db_t* p_vlan_port_db)
{
    uint32 entry_id = 0;
    ctc_port_scl_property_t scl_prop;

    /** Enable scl lookup double vlan for onu and pon qinq */
    ( p_vlan_port_db->scl_id == 2 )? p_port_db->flex_pon_cnt--: p_port_db->flex_onu_cnt--;
    if( (0==p_port_db->flex_pon_cnt && p_vlan_port_db->scl_id == 2) ||
        (0==p_port_db->flex_onu_cnt && p_vlan_port_db->scl_id == 3))
    {
        sal_memset(&scl_prop, 0, sizeof(scl_prop));
        scl_prop.scl_id = p_vlan_port_db->scl_id;
        scl_prop.direction = CTC_INGRESS;
        scl_prop.hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
        scl_prop.tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_DISABLE;
        scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
         CTC_ERROR_DUMP(sys_usw_port_set_scl_property(lchip, p_vlan_port_db->gport, &scl_prop));
    }

    SYS_PON_DBG_INFO("flex pon cnt: %d, flex onu cnt: %d\n", p_port_db->flex_pon_cnt, p_port_db->flex_onu_cnt);

    entry_id = ENCODE_SCL_VLAN_ENTRY_ID(p_vlan_port_db->vlan_port_id);
    sys_usw_scl_uninstall_entry(lchip, entry_id, 0);
    sys_usw_scl_remove_entry(lchip, entry_id, 0);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_pon_vlan_port_add_downlink_scl_entry(uint8 lchip,
                                              uint16 logic_port, 
                                              uint16 pkt_cvlan,
                                              sys_pon_vlan_port_db_t* p_vlan_port_db )
{
    uint32 vlan_mapping_port = 0;
    ctc_vlan_mapping_t vlan_mapping;
    int32 ret = CTC_E_NONE;

    sal_memset(&vlan_mapping, 0, sizeof(vlan_mapping));
    SYS_PON_SET_VLANMAPPING_KEY_TYPE();
    vlan_mapping.old_cvid = pkt_cvlan;

    CTC_SET_FLAG(vlan_mapping.flag, CTC_VLAN_MAPPING_FLAG_USE_LOGIC_PORT);
    vlan_mapping_port = logic_port;
    vlan_mapping.scl_id = p_vlan_port_db->scl_id;

    CTC_SET_FLAG(vlan_mapping.action, CTC_VLAN_MAPPING_OUTPUT_FID);
    vlan_mapping.u3.fid = p_vlan_port_db->fid;

    ret = sys_usw_vlan_add_vlan_mapping(lchip, vlan_mapping_port, &vlan_mapping);
    if (CTC_E_HASH_CONFLICT == ret)
    {
        CTC_SET_FLAG(vlan_mapping.flag, CTC_VLAN_MAPPING_FLAG_USE_FLEX);
        CTC_ERROR_RETURN(sys_usw_vlan_add_vlan_mapping(lchip, vlan_mapping_port , &vlan_mapping));
    }
    else if (ret != CTC_E_NONE)
    {
        return ret;
    }
    
    if(!p_vlan_port_db->scl_eid)
    {
        p_vlan_port_db->scl_eid = vlan_mapping.scl_entry_id;
    }
    return CTC_E_NONE;
}
                                              
STATIC int32
_sys_usw_pon_vlan_port_remove_downlink_scl_entry(uint8 lchip,
                                                 uint16 logic_port,
                                                 uint16 pkt_cvlan,
                                                 sys_pon_vlan_port_db_t* p_vlan_port_db)
{
    ctc_vlan_mapping_t vlan_mapping;
    uint32 vlan_mapping_port = 0;
    int32 ret = 0;

    sal_memset(&vlan_mapping, 0, sizeof(vlan_mapping));
    SYS_PON_SET_VLANMAPPING_KEY_TYPE();
    vlan_mapping.old_cvid = pkt_cvlan;
    
    CTC_SET_FLAG(vlan_mapping.flag, CTC_VLAN_MAPPING_FLAG_USE_LOGIC_PORT);
    vlan_mapping_port = logic_port;
    vlan_mapping.scl_id = p_vlan_port_db->scl_id;

    ret = sys_usw_vlan_remove_vlan_mapping(lchip, vlan_mapping_port , &vlan_mapping);
    if(CTC_E_NOT_EXIST == ret)
    {
        CTC_SET_FLAG(vlan_mapping.flag, CTC_VLAN_MAPPING_FLAG_USE_FLEX);
        CTC_ERROR_RETURN(sys_usw_vlan_remove_vlan_mapping(lchip, vlan_mapping_port , &vlan_mapping));
    }

    return ret;
}

STATIC int32
_sys_usw_pon_build_flex_vlan_key(uint8 lchip,
                                           uint32 group_id,
                                           uint32 entry_id,
                                           ctc_scl_tcam_ipv4_key_t* p_ctc_key,
                                           ctc_scl_igs_action_t* p_ctc_action)
{
    uint8  is_pon = (p_ctc_key->port_data.type == CTC_FIELD_PORT_TYPE_GPORT);
    int32  ret = CTC_E_NONE;
    ctc_scl_entry_t scl_entry;
    ctc_field_key_t field_key;
    ctc_scl_field_action_t field_action;

    /* add entry */
    sal_memset(&scl_entry, 0, sizeof(ctc_scl_entry_t));
    scl_entry.action_type = CTC_SCL_ACTION_INGRESS;
    scl_entry.entry_id = entry_id;
    scl_entry.key_type = CTC_SCL_KEY_TCAM_IPV4;
    scl_entry.mode = 1;
    CTC_ERROR_GOTO(sys_usw_scl_add_entry(lchip, group_id, &scl_entry, 0), ret, rollback);
    /* add port */
    sal_memset(&field_key, 0, sizeof(ctc_field_key_t));
    field_key.ext_data = &p_ctc_key->port_data;
    field_key.ext_mask = &p_ctc_key->port_mask;
    field_key.type = CTC_FIELD_KEY_PORT;
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &field_key), ret, rollback);
    /* add svlan range */
    sal_memset(&field_key, 0, sizeof(ctc_field_key_t));
    field_key.data = p_ctc_key->svlan;
    field_key.mask = p_ctc_key->svlan_mask;
    field_key.type = CTC_FIELD_KEY_SVLAN_ID;
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &field_key), ret, rollback);
    /* add cvlan */
    sal_memset(&field_key, 0, sizeof(ctc_field_key_t));
    field_key.data = p_ctc_key->cvlan;
    field_key.mask = p_ctc_key->cvlan_mask;
    field_key.type = CTC_FIELD_KEY_CVLAN_ID;
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &field_key), ret, rollback);
    /* add action fid */
    if (CTC_FLAG_ISSET(p_ctc_action->flag, CTC_SCL_IGS_ACTION_FLAG_FID))
    {
        sal_memset(&field_action, 0, sizeof(ctc_scl_field_action_t));
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_FID;
        field_action.data0 = p_ctc_action->fid;
        CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, rollback);
    }
    /* add action logic port */
    if (CTC_FLAG_ISSET(p_ctc_action->flag, CTC_SCL_IGS_ACTION_FLAG_LOGIC_PORT))
    {
        sal_memset(&field_action, 0, sizeof(ctc_scl_field_action_t));
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_LOGIC_PORT;
        field_action.ext_data = &p_ctc_action->logic_port;
        CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, rollback);
    }
    /* add action policer */
    if (p_ctc_action->policer_id > 0)
    {
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_POLICER_ID;
        field_action.data0 = p_ctc_action->policer_id;
        field_action.data1 = 1; /* service policer en */
        CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, rollback);
    }
    /* add action vlan edit */
    if (CTC_FLAG_ISSET(p_ctc_action->flag, CTC_SCL_IGS_ACTION_FLAG_VLAN_EDIT))
    {
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_VLAN_EDIT;
        field_action.ext_data = &p_ctc_action->vlan_edit;
        CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, rollback);
    }
    /* add action priority */
    sal_memset(&field_action, 0, sizeof(ctc_scl_field_action_t));
    field_action.type = CTC_SCL_FIELD_ACTION_TYPE_CHANGE_LKUP_PRI;
    field_action.data0 = is_pon ? CTC_PON_PRI_SVRANG_CVID : CTC_PON_PRI_TUN_SVRANG_CVID;
    CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, rollback);
    /* install entry */
    CTC_ERROR_GOTO(sys_usw_scl_install_entry(lchip, entry_id, 0), ret, rollback);
    return CTC_E_NONE;

rollback:
    sys_usw_scl_uninstall_entry(lchip, entry_id, 0);
    sys_usw_scl_remove_entry(lchip, entry_id, 0);
    return ret;
}

int32
_sys_usw_pon_vlan_port_basic_create(uint8 lchip,
                             ctc_pon_vlan_port_t* p_vlan_port,
                             sys_pon_vlan_port_db_t* p_vlan_port_db,
                             sys_pon_port_db_t* p_port_db)
{
    int32 ret = 0;
    uint32 vlan_mapping_port = 0;
    ctc_vlan_mapping_t vlan_mapping;
    ctc_scl_tcam_ipv4_key_t flex_vlan_key;
    ctc_scl_igs_action_t flex_vlan_action;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;
    uint32 flex_vlan_gid;
    uint32 flex_vlan_eid;
    p_gem_port_db = p_vlan_port_db->p_gem_port_db;

    if ( CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_PON_SERVICE))
    {
        p_vlan_port_db->egs_vlan_mapping_en = 1;
    }

    if (CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_PASS_THROUGH))
    {
        p_vlan_port_db->pass_through_en = 1;
    }

    if (1 == p_vlan_port_db->egs_vlan_mapping_en)
    {
        if(!p_vlan_port_db->pass_through_en)
        {
            CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_downlink_scl_add(lchip, p_vlan_port, p_vlan_port_db,  p_port_db), ret, roll_back_0);
        }
    }
    else
    {
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_downlink_nexthop_add(lchip, p_vlan_port, p_vlan_port_db,  p_port_db), ret, roll_back_0);
    }

    /* Add vlan mapping */
    sal_memset(&vlan_mapping, 0, sizeof(vlan_mapping));
    SYS_PON_SET_VLANMAPPING_KEY_TYPE();

    /* Add vlan range */
    if (p_vlan_port_db->match_svlan_end)
    {
        ctc_vlan_range_info_t range_info;
        ctc_vlan_range_t vlan_range;

        sal_memset(&range_info, 0, sizeof(range_info));
        sal_memset(&vlan_range, 0, sizeof(vlan_range));

        CTC_ERROR_GOTO(_sys_usw_pon_vlan_range_group_en(lchip, p_vlan_port->gport, TRUE), ret, roll_back_1);
        range_info.direction = CTC_INGRESS;
        range_info.vrange_grpid = p_port_db->vlan_range_grp;
        vlan_range.vlan_start = p_vlan_port_db->match_svlan;
        vlan_range.vlan_end   = p_vlan_port_db->match_svlan_end;
        SYS_PON_DBG_INFO("vlan range group id: %d, vlan start: %d, vlan end: %d\n", range_info.vrange_grpid, vlan_range.vlan_start,vlan_range.vlan_end);
        CTC_ERROR_GOTO(sys_usw_vlan_add_vlan_range_member(lchip, &range_info, &vlan_range), ret, roll_back_2);

        vlan_mapping.svlan_end = p_vlan_port_db->match_svlan_end;
        vlan_mapping.vrange_grpid = p_port_db->vlan_range_grp;
    }

    if (!p_vlan_port_db->egs_vlan_mapping_en && p_gem_port_db)
    {
        /* src port key */
        vlan_mapping.flag = CTC_VLAN_MAPPING_FLAG_USE_LOGIC_PORT;
        vlan_mapping_port = p_vlan_port_db->acl_logic_port ? p_vlan_port_db->acl_logic_port : p_gem_port_db->logic_port;
        vlan_mapping.scl_id = CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_SCL_ID)? p_vlan_port->scl_id : 0;
        CTC_SET_FLAG(vlan_mapping.action, CTC_VLAN_MAPPING_OUTPUT_LOGIC_SRC_PORT);
        vlan_mapping.logic_src_port = p_vlan_port_db->logic_port;
    }
    else
    {
        vlan_mapping_port = p_vlan_port->gport;
        vlan_mapping.scl_id = CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_SCL_ID)? p_vlan_port->scl_id : 1;
    }

    CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_vlan_mapping(lchip, p_vlan_port, &vlan_mapping, NULL), ret, roll_back_3);

    CTC_SET_FLAG(vlan_mapping.action, CTC_VLAN_MAPPING_OUTPUT_FID);
    vlan_mapping.u3.fid = p_vlan_port_db->fid;

    if (p_vlan_port->igs_policer_id)
    {
        CTC_SET_FLAG(vlan_mapping.action, CTC_VLAN_MAPPING_FLAG_SERVICE_POLICER_EN);
        vlan_mapping.policer_id = p_vlan_port->igs_policer_id;
    }
    if (0 != p_vlan_port_db->match_svlan_end)
    {
        CTC_SET_FLAG(vlan_mapping.flag, CTC_VLAN_MAPPING_FLAG_USE_FLEX);
        p_vlan_port_db->igs_vlan_mapping_use_flex = 1;
    }
    if (DRV_FROM_TMM(lchip)&& p_vlan_port_db->match_svlan_end)
    {
        sal_memset(&flex_vlan_action, 0, sizeof(flex_vlan_action));
        sal_memset(&flex_vlan_key, 0, sizeof(flex_vlan_key));
        flex_vlan_eid = ENCODE_SCL_UPLINK_ENTRY_ID(p_vlan_port_db->vlan_port_id, 0);
        flex_vlan_key.svlan = p_vlan_port_db->match_svlan_end;
        flex_vlan_key.svlan_mask = 0xFFF;
        flex_vlan_key.cvlan = p_vlan_port_db->match_cvlan;
        flex_vlan_key.cvlan_mask = 0xFFF;
        if (!p_vlan_port_db->egs_vlan_mapping_en && p_gem_port_db)
        {
            flex_vlan_key.port_data.type = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
            flex_vlan_key.port_data.logic_port = p_gem_port_db->logic_port;
            flex_vlan_key.port_mask.type = 0xFF;
            flex_vlan_key.port_mask.logic_port = 0xFFFF;
            CTC_SET_FLAG(flex_vlan_action.flag, CTC_SCL_IGS_ACTION_FLAG_LOGIC_PORT);
            flex_vlan_action.logic_port.logic_port = p_vlan_port_db->logic_port;
            flex_vlan_action.logic_port.logic_port_type = 0;
            flex_vlan_action.logic_port.binding_en = 0;
        }
        else
        {
            flex_vlan_key.port_data.type = CTC_FIELD_PORT_TYPE_GPORT;
            flex_vlan_key.port_data.gport = p_vlan_port->gport;
            flex_vlan_key.port_mask.type = 0xFF;
            flex_vlan_key.port_mask.gport = 0xFFFF;
        }
        flex_vlan_gid = CTC_SCL_GROUP_ID_TCAM2 + vlan_mapping.scl_id;
        CTC_SET_FLAG(flex_vlan_action.flag, CTC_SCL_IGS_ACTION_FLAG_FID);
        flex_vlan_action.fid = p_vlan_port_db->fid;
        if (p_vlan_port->igs_policer_id)
        {
            flex_vlan_action.policer_id = p_vlan_port->igs_policer_id;
        }
        CTC_SET_FLAG(flex_vlan_action.flag, CTC_SCL_IGS_ACTION_FLAG_VLAN_EDIT);
        flex_vlan_action.vlan_edit.ccos_new = vlan_mapping.new_ccos;
        flex_vlan_action.vlan_edit.ccos_sl = vlan_mapping.ccos_sl;
        flex_vlan_action.vlan_edit.ctag_op = vlan_mapping.ctag_op;
        flex_vlan_action.vlan_edit.cvid_new = vlan_mapping.new_cvid;
        flex_vlan_action.vlan_edit.cvid_sl = vlan_mapping.cvid_sl;
        flex_vlan_action.vlan_edit.scos_new = vlan_mapping.new_scos;
        flex_vlan_action.vlan_edit.scos_sl = vlan_mapping.scos_sl;
        flex_vlan_action.vlan_edit.stag_op = vlan_mapping.stag_op;
        flex_vlan_action.vlan_edit.svid_new = vlan_mapping.new_svid;
        flex_vlan_action.vlan_edit.svid_sl = vlan_mapping.svid_sl;
        CTC_ERROR_GOTO(_sys_usw_pon_build_flex_vlan_key(lchip, flex_vlan_gid, flex_vlan_eid, &flex_vlan_key, &flex_vlan_action), ret, roll_back_3);
        p_vlan_port->scl_eid = flex_vlan_eid;
    }
    else
    {
        ret = sys_usw_vlan_add_vlan_mapping(lchip, vlan_mapping_port, &vlan_mapping);
        if (ret ==  CTC_E_HASH_CONFLICT)
        {
            SYS_PON_DBG_INFO("Hash Confict!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
            CTC_SET_FLAG(vlan_mapping.flag, CTC_VLAN_MAPPING_FLAG_USE_FLEX);
            CTC_ERROR_GOTO(sys_usw_vlan_add_vlan_mapping(lchip, vlan_mapping_port , &vlan_mapping), ret, roll_back_3);
            p_vlan_port_db->igs_vlan_mapping_use_flex = 1;
        }
        else if(ret != CTC_E_NONE)
        {
            goto roll_back_3;
        }
        p_vlan_port->scl_eid = vlan_mapping.scl_entry_id;
    }
    p_vlan_port_db->scl_id = vlan_mapping.scl_id;
    
    return CTC_E_NONE;

    /*-----------------------------------------------------------
    *** rool back
    -----------------------------------------------------------*/


roll_back_3:
    if (p_vlan_port_db->match_svlan_end)
    {
        ctc_vlan_range_info_t range_info;
        ctc_vlan_range_t vlan_range;

        sal_memset(&range_info, 0, sizeof(range_info));
        sal_memset(&vlan_range, 0, sizeof(vlan_range));

        range_info.direction = CTC_INGRESS;
        range_info.vrange_grpid = p_port_db->vlan_range_grp;
        vlan_range.vlan_start = p_vlan_port_db->match_svlan;
        vlan_range.vlan_end   = p_vlan_port_db->match_svlan_end;
        SYS_PON_DBG_INFO("vlan range group id: %d, vlan start: %d, vlan end: %d\n", range_info.vrange_grpid, vlan_range.vlan_start,vlan_range.vlan_end);
        sys_usw_vlan_remove_vlan_range_member(lchip, &range_info, &vlan_range);
    }
roll_back_2:
    if (p_vlan_port_db->match_svlan_end)
    {
        _sys_usw_pon_vlan_range_group_en(lchip, p_vlan_port->gport, FALSE);
    }
roll_back_1:
    if (1 == p_vlan_port_db->egs_vlan_mapping_en)
    {
        if(!p_vlan_port_db->pass_through_en)
        {
            _sys_usw_pon_vlan_port_downlink_scl_remove(lchip, p_vlan_port_db, p_port_db);
        }
    }
    else
    {
        _sys_usw_pon_vlan_port_downlink_nexthop_remove(lchip, p_vlan_port_db, p_port_db);
    }

roll_back_0:

    return ret;
}

int32
_sys_usw_pon_vlan_port_basic_destroy(uint8 lchip,
                             sys_pon_vlan_port_db_t* p_vlan_port_db,
                             sys_pon_port_db_t* p_port_db)
{
    int32 ret = 0;
    uint32 vlan_mapping_port = 0;
    uint32 flex_vlan_eid;
    ctc_vlan_mapping_t vlan_mapping;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;

    p_gem_port_db = p_vlan_port_db->p_gem_port_db;

    /* Remove vlan mapping */
    sal_memset(&vlan_mapping, 0, sizeof(vlan_mapping));


    if(!p_vlan_port_db->egs_vlan_mapping_en)
    {
        vlan_mapping.flag = CTC_VLAN_MAPPING_FLAG_USE_LOGIC_PORT;
        vlan_mapping_port =  p_vlan_port_db->acl_logic_port ? p_vlan_port_db->acl_logic_port : p_gem_port_db->logic_port;
    }
    else
    {
        vlan_mapping_port = p_vlan_port_db->gport;
        
    }
    
    vlan_mapping.scl_id = p_vlan_port_db->scl_id;
    SYS_PON_SET_VLANMAPPING_KEY_TYPE();
    vlan_mapping.svlan_end = p_vlan_port_db->match_svlan_end;
    vlan_mapping.vrange_grpid = p_port_db->vlan_range_grp;

    if (p_vlan_port_db->igs_vlan_mapping_use_flex)
    {
        CTC_SET_FLAG(vlan_mapping.flag, CTC_VLAN_MAPPING_FLAG_USE_FLEX);
    }

    if(DRV_FROM_TMM(lchip)&&p_vlan_port_db->match_svlan_end)
    {
        flex_vlan_eid = ENCODE_SCL_UPLINK_ENTRY_ID(p_vlan_port_db->vlan_port_id, 0);
        sys_usw_scl_uninstall_entry(lchip, flex_vlan_eid, 0);
        sys_usw_scl_remove_entry(lchip, flex_vlan_eid, 0);
    }
    else
    {
        sys_usw_vlan_remove_vlan_mapping(lchip, vlan_mapping_port , &vlan_mapping);
    }

    /* Remove vlan range */
    if (p_vlan_port_db->match_svlan_end)
    {
        ctc_vlan_range_info_t range_info;
        ctc_vlan_range_t vlan_range;

        sal_memset(&range_info, 0, sizeof(range_info));
        sal_memset(&vlan_range, 0, sizeof(vlan_range));

        range_info.direction = CTC_INGRESS;
        range_info.vrange_grpid = p_port_db->vlan_range_grp;
        vlan_range.vlan_start = p_vlan_port_db->match_svlan;
        vlan_range.vlan_end   = p_vlan_port_db->match_svlan_end;
        SYS_PON_DBG_INFO("vlan range group id: %d, vlan start: %d, vlan end: %d\n", range_info.vrange_grpid, vlan_range.vlan_start,vlan_range.vlan_end);
        sys_usw_vlan_remove_vlan_range_member(lchip, &range_info, &vlan_range);
        _sys_usw_pon_vlan_range_group_en(lchip, p_vlan_port_db->gport, FALSE);
    }

    if (1 == p_vlan_port_db->egs_vlan_mapping_en)
    {
        if(!p_vlan_port_db->pass_through_en)
        {
            _sys_usw_pon_vlan_port_downlink_scl_remove(lchip, p_vlan_port_db,  p_port_db);
        }
    }
    else
    {
        _sys_usw_pon_vlan_port_downlink_nexthop_remove(lchip, p_vlan_port_db,  p_port_db);
    }

    return ret;
}



int32
_sys_usw_pon_vlan_port_flex_create(uint8 lchip,
                                   ctc_pon_vlan_port_t* p_vlan_port,
                                   sys_pon_vlan_port_db_t* p_vlan_port_db,
                                   sys_pon_port_db_t* p_port_db)
{
    int32 ret = 0;
    uint8 i = 0;
    uint8 tcam_type = 0;
    uint8 scl_id = 0;
    uint32 entry_id = 0;
    uint32 group_id = 0;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;
    ctc_field_key_t field_key;
    ctc_field_port_t field_port;
    ctc_field_port_t field_port_mask;
    ctc_scl_field_action_t field_action;
    ctc_scl_vlan_edit_t vlan_edit;
    ctc_port_scl_property_t scl_prop;
    ctc_scl_entry_t scl_entry;

    p_gem_port_db = p_vlan_port_db->p_gem_port_db;

    if ( CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_PON_SERVICE))
    {
        p_vlan_port_db->egs_vlan_mapping_en = 1;
    }

    if (1 == p_vlan_port_db->egs_vlan_mapping_en)
    {
        scl_id = CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_SCL_ID)? p_vlan_port->scl_id : 3;
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_downlink_scl_add(lchip, p_vlan_port, p_vlan_port_db,  p_port_db), ret, roll_back_0);
    }
    else
    {
        scl_id = CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_SCL_ID)? p_vlan_port->scl_id : 2;
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_downlink_nexthop_add(lchip, p_vlan_port, p_vlan_port_db,  p_port_db), ret, roll_back_0);
    }
    
    group_id = (scl_id == 2) ? CTC_SCL_GROUP_ID_TCAM2 : CTC_SCL_GROUP_ID_TCAM3;
    entry_id = ENCODE_SCL_UPLINK_ENTRY_ID(p_vlan_port_db->vlan_port_id, 0);

    sal_memset(&scl_entry, 0, sizeof(ctc_scl_entry_t));
    if (p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_FLEX_MAC)
    {
        scl_entry.key_type = CTC_SCL_KEY_TCAM_MAC;
        tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_MAC;
    }
    else if(p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_FLEX_IPV4)
    {
        scl_entry.key_type = CTC_SCL_KEY_TCAM_IPV4;
        tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_IP;
    }
    else if(p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_FLEX_IPV6)
    {
        scl_entry.key_type = CTC_SCL_KEY_TCAM_IPV6;
        tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_IP;
    }

    scl_entry.mode = 1;
    scl_entry.action_type =  CTC_SCL_ACTION_INGRESS;
    scl_entry.entry_id = entry_id;
    if(DRV_FROM_TMM(lchip))
    {
        scl_entry.priority = CTC_PON_FLEX_EPRI;
        scl_entry.priority_valid  =1;
    }
    CTC_ERROR_GOTO(sys_usw_scl_add_entry(lchip, group_id, &scl_entry, 0), ret, roll_back_1);

    sal_memset(&field_key, 0, sizeof(ctc_field_key_t));
    sal_memset(&field_port, 0, sizeof(ctc_field_port_t));
    sal_memset(&field_port_mask, 0xFF, sizeof(ctc_field_port_t));
    field_key.type = CTC_FIELD_KEY_PORT;
    if (p_vlan_port_db->egs_vlan_mapping_en)
    {
        field_port.gport = p_vlan_port->gport;
        field_port.type = CTC_FIELD_PORT_TYPE_GPORT;
    }
    else if (p_gem_port_db)
    {
        field_port.logic_port = p_gem_port_db->logic_port;
        field_port.type = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
    }
    field_key.ext_data = &field_port;
    field_key.ext_mask = &field_port_mask;
    CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &field_key), ret, roll_back_2);

    for (i = 0; i < p_vlan_port->fields_num; i++)
    {
        CTC_ERROR_GOTO(sys_usw_scl_add_key_field(lchip, entry_id, &p_vlan_port->match_fields[i]), ret, roll_back_2);
    }

    if (!p_vlan_port_db->egs_vlan_mapping_en)
    {
        ctc_scl_logic_port_t logic_dest_port;
        sal_memset(&field_action, 0, sizeof(ctc_scl_field_action_t));
        sal_memset(&logic_dest_port, 0, sizeof(ctc_scl_logic_port_t));
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_LOGIC_PORT;
        logic_dest_port.logic_port = p_vlan_port_db->logic_port;
        logic_dest_port.logic_port_type = 0;
        field_action.ext_data = &logic_dest_port;
        CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, roll_back_2);
    }

    field_action.type = CTC_SCL_FIELD_ACTION_TYPE_VLAN_EDIT;
    sal_memset(&vlan_edit, 0, sizeof(ctc_scl_vlan_edit_t));
    CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_vlan_mapping(lchip, p_vlan_port, NULL, &vlan_edit), ret, roll_back_2);
    field_action.ext_data = &vlan_edit;
    CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, roll_back_2);
    if (DRV_FROM_TMM(lchip))
    {
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_CHANGE_LKUP_PRI;
        field_action.data0 = (p_vlan_port_db->egs_vlan_mapping_en == 1) ? CTC_PON_PRI_FLEX : CTC_PON_PRI_TUN_FLEX;
        CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, roll_back_2);
    }

    if (p_vlan_port->igs_policer_id)
    {
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_POLICER_ID;
        field_action.data0 = p_vlan_port->igs_policer_id;
        field_action.data1 = 1;
        CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, roll_back_2);
    }

    field_action.type = CTC_SCL_FIELD_ACTION_TYPE_FID;
    field_action.data0 = p_vlan_port_db->fid;
    CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &field_action), ret, roll_back_2);

    CTC_ERROR_GOTO(sys_usw_scl_install_entry(lchip, entry_id, 0), ret, roll_back_2);

    /** Enable scl lookup double vlan for onu and pon qinq */
    sal_memset(&scl_prop, 0, sizeof(scl_prop));
    sys_usw_port_api_get_scl_property(lchip, p_vlan_port_db->gport, &scl_prop);
    if (tcam_type!=scl_prop.tcam_type && CTC_PORT_IGS_SCL_TCAM_TYPE_RESOLVE_CONFLICT!=scl_prop.tcam_type)
    {
        SYS_PON_DBG_ERROR("Tcam type must keep the same when update!\n");
        ret = CTC_E_INVALID_PARAM;
        goto roll_back_3;
    }

    if ((0 == p_port_db->flex_pon_cnt && scl_id == 2) || \
        (0 == p_port_db->flex_onu_cnt && scl_id == 3))
    {
        sal_memset(&scl_prop, 0, sizeof(scl_prop));
        scl_prop.scl_id = scl_id;
        scl_prop.direction = CTC_INGRESS;
        scl_prop.hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
        scl_prop.use_logic_port_en = p_vlan_port_db->egs_vlan_mapping_en?0:1;
        scl_prop.tcam_type = tcam_type;
        scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
        CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip, p_vlan_port_db->gport, &scl_prop), ret, roll_back_3);
    }
    (scl_id == 2) ? p_port_db->flex_pon_cnt++: p_port_db->flex_onu_cnt++;
    SYS_PON_DBG_INFO("flex pon cnt: %d, flex onu cnt: %d\n", p_port_db->flex_pon_cnt, p_port_db->flex_onu_cnt);
    p_vlan_port->scl_eid = entry_id;
    p_vlan_port_db->scl_id = scl_id;

    return CTC_E_NONE;

    /*-----------------------------------------------------------
    *** rool back
    -----------------------------------------------------------*/
roll_back_3:
    sys_usw_scl_uninstall_entry(lchip, entry_id, 0);

roll_back_2:
    sys_usw_scl_remove_entry(lchip, entry_id, 0);

roll_back_1:
    if (1 == p_vlan_port_db->egs_vlan_mapping_en)
    {
        _sys_usw_pon_vlan_port_downlink_scl_remove(lchip, p_vlan_port_db, p_port_db);
    }
    else
    {
        _sys_usw_pon_vlan_port_downlink_nexthop_remove(lchip, p_vlan_port_db, p_port_db);
    }

roll_back_0:

    return ret;
}

int32
_sys_usw_pon_vlan_port_flex_destroy(uint8 lchip,
                                    sys_pon_vlan_port_db_t* p_vlan_port_db,
                                    sys_pon_port_db_t *p_port_db)
{
    uint32 entry_id = 0;
    ctc_port_scl_property_t scl_prop;

    /** Enable scl lookup double vlan for onu and pon qinq */
    ( p_vlan_port_db->scl_id == 2 )? p_port_db->flex_pon_cnt--: p_port_db->flex_onu_cnt--;
    if ((0==p_port_db->flex_pon_cnt && p_vlan_port_db->scl_id == 2) || \
        (0==p_port_db->flex_onu_cnt && p_vlan_port_db->scl_id == 3))
    {
        sal_memset(&scl_prop, 0, sizeof(scl_prop));
        scl_prop.scl_id = p_vlan_port_db->scl_id;
        scl_prop.direction = CTC_INGRESS;
        scl_prop.hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
        scl_prop.tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_DISABLE;
        scl_prop.use_logic_port_en = p_vlan_port_db->egs_vlan_mapping_en?0:1;
        scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
        CTC_ERROR_DUMP(sys_usw_port_api_set_scl_property(lchip, p_vlan_port_db->gport, &scl_prop));
    }

    SYS_PON_DBG_INFO("flex pon cnt: %d, flex onu cnt: %d\n", p_port_db->flex_pon_cnt, p_port_db->flex_onu_cnt);

    entry_id = ENCODE_SCL_UPLINK_ENTRY_ID(p_vlan_port_db->vlan_port_id, 0);
    sys_usw_scl_uninstall_entry(lchip, entry_id, 0);
    sys_usw_scl_remove_entry(lchip, entry_id, 0);

    if (1 == p_vlan_port_db->egs_vlan_mapping_en)
    {
        _sys_usw_pon_vlan_port_downlink_scl_remove(lchip, p_vlan_port_db, p_port_db);
    }
    else
    {
        _sys_usw_pon_vlan_port_downlink_nexthop_remove(lchip, p_vlan_port_db, p_port_db);
    }

    return CTC_E_NONE;
}

int32
_sys_usw_pon_vlan_port_build_egress_key(uint8 lchip,
                                    sys_pon_vlan_port_db_t* p_vlan_port_db, uint16 logic_dest_port, uint32 entry_id, sys_scl_lkup_key_t* lkup_key, uint8 is_add)
{
    ctc_field_key_t key_field;
    ctc_field_port_t p_port;

    sal_memset(&key_field, 0, sizeof(key_field));
    sal_memset(&p_port, 0, sizeof(p_port));
    p_port.type = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
    p_port.logic_port = logic_dest_port;
    key_field.ext_data = &p_port;
    key_field.type = CTC_FIELD_KEY_DST_GPORT;
    if(is_add)
    {
        CTC_ERROR_RETURN(sys_usw_scl_add_key_field(lchip, entry_id, &key_field));
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_scl_construct_lkup_key(lchip, &key_field, lkup_key));
    }
    sal_memset(&key_field, 0, sizeof(key_field));
    p_port.type = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
    p_port.logic_port = p_vlan_port_db->logic_port;
    key_field.ext_data = &p_port;
    key_field.type = CTC_FIELD_KEY_PORT;
    if(is_add)
    {
        CTC_ERROR_RETURN(sys_usw_scl_add_key_field(lchip, entry_id, &key_field));
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_scl_construct_lkup_key(lchip, &key_field, lkup_key));
    }
    sal_memset(&key_field, 0, sizeof(key_field));
    key_field.type = CTC_FIELD_KEY_HASH_VALID;
    key_field.data = 1;
    if(is_add)
    {
        CTC_ERROR_RETURN(sys_usw_scl_add_key_field(lchip, entry_id, &key_field));
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_scl_construct_lkup_key(lchip, &key_field, lkup_key));
    }
    if(!is_add)
    {
        key_field.type = SYS_SCL_FIELD_KEY_COMMON;
        sys_usw_scl_construct_lkup_key(lchip, &key_field, lkup_key);
    }

    return CTC_E_NONE;
}

int32
_sys_usw_pon_vlan_port_uplink_vn_tag_entry_create(uint8 lchip,
                                    sys_pon_vlan_port_db_t* p_vlan_port_db, ctc_pon_vlan_port_t* p_vlan_port, uint8 is_update)
{
    int32 ret = 0;
    uint32 gid = 0;
    uint32 entry_id =0;
    uint16 logic_dest_port = 0;
    ctc_scl_field_action_t action_field;
    ctc_scl_vlan_edit_t vlan_edit;
    ctc_scl_entry_t  scl_entry;
    sys_scl_lkup_key_t lkup_key;

    if(!is_update)
    {
        sal_memset(&scl_entry, 0, sizeof(scl_entry));
        scl_entry.key_type = SYS_SCL_KEY_HASH_PORT_CROSS;
        scl_entry.action_type = CTC_SCL_ACTION_EGRESS;
        scl_entry.mode = 1;
        gid = CTC_SCL_GROUP_ID_HASH_PORT;
        CTC_ERROR_GOTO(sys_usw_scl_add_entry(lchip, gid, &scl_entry, 1), ret, roll_back_0);
        entry_id =  scl_entry.entry_id;
        logic_dest_port = p_vlan_port->logic_dest_port;
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_build_egress_key(lchip, p_vlan_port_db, logic_dest_port, entry_id, &lkup_key, 1), ret, roll_back_1);
    }
    else
    {
        sal_memset(&lkup_key, 0, sizeof(lkup_key));
        gid = CTC_SCL_GROUP_ID_HASH_PORT;
        lkup_key.key_type = SYS_SCL_KEY_HASH_PORT_CROSS;
        lkup_key.action_type = CTC_SCL_ACTION_EGRESS;
        lkup_key.group_id = gid;
        logic_dest_port = p_vlan_port_db->logic_dest_port;
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_build_egress_key(lchip, p_vlan_port_db, logic_dest_port, entry_id, &lkup_key, 0), ret, roll_back_1);
        sys_usw_scl_get_entry_id_by_lkup_key(lchip, &lkup_key);
        entry_id = lkup_key.entry_id;
        if(p_vlan_port_db->logic_dest_port!= p_vlan_port->logic_dest_port)
        {
            sys_usw_scl_uninstall_entry(lchip, entry_id, 1);
            sys_usw_scl_remove_entry(lchip, entry_id, 1);
            sal_memset(&scl_entry, 0, sizeof(scl_entry));
            scl_entry.key_type = SYS_SCL_KEY_HASH_PORT_CROSS;
            scl_entry.action_type = CTC_SCL_ACTION_EGRESS;
            scl_entry.mode = 1;
            gid = CTC_SCL_GROUP_ID_HASH_PORT;
            CTC_ERROR_GOTO(sys_usw_scl_add_entry(lchip, gid, &scl_entry, 1), ret, roll_back_0);
            entry_id =  scl_entry.entry_id;
            logic_dest_port = p_vlan_port->logic_dest_port;
            _sys_usw_pon_vlan_port_build_egress_key(lchip, p_vlan_port_db, logic_dest_port, entry_id, &lkup_key, 1);
        }
    }

    sal_memset(&action_field, 0, sizeof(action_field));
    sal_memset(&vlan_edit, 0, sizeof(vlan_edit));
    action_field.type = CTC_SCL_FIELD_ACTION_TYPE_VLAN_EDIT;
    action_field.ext_data = &vlan_edit;
    vlan_edit.vlan_domain = CTC_SCL_VLAN_DOMAIN_SVLAN;
    vlan_edit.stag_op = CTC_ACL_VLAN_TAG_OP_ADD;
    vlan_edit.svid_sl = CTC_ACL_VLAN_TAG_SL_NEW;
    vlan_edit.svid_new = p_vlan_port->vn_tag;
    CTC_ERROR_GOTO(sys_usw_scl_add_action_field(lchip, entry_id, &action_field), ret, roll_back_1);

    CTC_ERROR_GOTO(sys_usw_scl_install_entry(lchip, entry_id, 1), ret, roll_back_1);


    return CTC_E_NONE;

    /*-----------------------------------------------------------
    *** rool back
    -----------------------------------------------------------*/

roll_back_1:
    if(!is_update)
    {
        sys_usw_scl_remove_entry(lchip, scl_entry.entry_id, 1);
    }

roll_back_0:

    return ret;
}

int32
_sys_usw_pon_vlan_port_uplink_vn_tag_entry_destroy(uint8 lchip,
                                    sys_pon_vlan_port_db_t* p_vlan_port_db)
{
    uint32 gid = 0;
    sys_scl_lkup_key_t lkup_key;

    sal_memset(&lkup_key, 0, sizeof(lkup_key));

    gid = CTC_SCL_GROUP_ID_HASH_PORT;
    lkup_key.key_type = SYS_SCL_KEY_HASH_PORT_CROSS;
    lkup_key.action_type = CTC_SCL_ACTION_EGRESS;
    lkup_key.group_id = gid;
    CTC_ERROR_RETURN(_sys_usw_pon_vlan_port_build_egress_key(lchip, p_vlan_port_db, p_vlan_port_db->logic_dest_port, 0, &lkup_key, 0));
    CTC_ERROR_RETURN(sys_usw_scl_get_entry_id_by_lkup_key(lchip, &lkup_key));
    CTC_ERROR_RETURN(sys_usw_scl_uninstall_entry(lchip, lkup_key.entry_id, 1));
    CTC_ERROR_RETURN(sys_usw_scl_remove_entry(lchip, lkup_key.entry_id, 1));

    return CTC_E_NONE;

}

int32
_sys_usw_pon_update_vlan_port_vn_tag(uint8 lchip, sys_pon_vlan_port_db_t* p_vlan_port_db, ctc_pon_vlan_port_t* p_vlan_port)
{
    uint8 is_update = 0;
    if(p_vlan_port_db->egs_vlan_mapping_en)
    {
        return CTC_E_NOT_SUPPORT;
    }

    if(p_vlan_port->vn_tag)
    {
        CTC_MAX_VALUE_CHECK(p_vlan_port->logic_dest_port, SYS_USW_SCL_LOGIC_PORT_MAX_NUM);
        is_update = p_vlan_port_db->vn_tag?1:0;
        CTC_ERROR_RETURN(_sys_usw_pon_vlan_port_uplink_vn_tag_entry_create(lchip, p_vlan_port_db, p_vlan_port, is_update));
        p_vlan_port_db->logic_dest_port = p_vlan_port->logic_dest_port;
    }
    else
    {
        CTC_ERROR_RETURN(_sys_usw_pon_vlan_port_uplink_vn_tag_entry_destroy(lchip, p_vlan_port_db));
        p_vlan_port_db->logic_dest_port = 0;
    }
    
    sys_usw_vlan_set_fid_mapping_vdev_vlan(lchip, p_vlan_port_db->fid, p_vlan_port->volt_tag, p_vlan_port->volt_tag_valid);
    
    p_vlan_port_db->vn_tag = p_vlan_port->vn_tag;

    return CTC_E_NONE;

}
int32
_sys_usw_pon_create_uni_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port)
{
    int32 ret = 0;
    uint16 lport = 0;
    sys_pon_port_db_t* p_port_db = NULL;
    sys_pon_gem_port_db_t gem_port_db;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;
    sys_pon_vlan_port_db_t* p_vlan_port_db = NULL;
    sys_pon_vlan_port_db_t vlan_port_db_tmp;

    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_vlan_port);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_vlan_port->gport, lchip, lport);
    SYS_PON_TUNNEL_VLAN_ID_CHECK(p_vlan_port->tunnel_value);
    SYS_PON_SCL_ID_CHECK(p_vlan_port);
    CTC_MAX_VALUE_CHECK(p_vlan_port->vn_tag, CTC_MAX_VLAN_ID);
    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         p_vlan_port->gport);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "tunnel_value",         p_vlan_port->tunnel_value);


    SYS_PON_LOCK(lchip);

    /* DB */
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

    if (0 == p_port_db->enable)
    {
        SYS_PON_UNLOCK(lchip);
       return CTC_E_NOT_READY;
    }

    if (!CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_PON_SERVICE))
    {
        sal_memset(&gem_port_db, 0, sizeof(gem_port_db));
        gem_port_db.gport = p_vlan_port->gport;
        gem_port_db.tunnel_value = p_vlan_port->tunnel_value;
        p_gem_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->gem_port_hash, &gem_port_db);

        if (NULL == p_gem_port_db)
        {
            SYS_PON_UNLOCK(lchip);
            return CTC_E_NOT_EXIST;
        }
    }

    sal_memset(&vlan_port_db_tmp, 0, sizeof(sys_pon_vlan_port_db_t));
    vlan_port_db_tmp.vlan_port_id = p_vlan_port->vlan_port_id;
    p_vlan_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->vlan_port_hash, &vlan_port_db_tmp);

    if (NULL != p_vlan_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_ENTRY_EXIST;
    }

    if(CTC_WB_ENABLE(lchip) && p_usw_pon_master[lchip]->vlan_port_hash->count >= SYS_WB_PON_VLAN_PORT_NUM)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NO_MEMORY;
    }

    /* Build node */
    MALLOC_PON_POINTER(sys_pon_vlan_port_db_t, p_vlan_port_db);
    if (NULL == p_vlan_port_db)
    {
        goto roll_back_0;
    }

    sal_memset(p_vlan_port_db, 0, sizeof(sys_pon_vlan_port_db_t));
    p_vlan_port_db->vlan_port_id = p_vlan_port->vlan_port_id;
    p_vlan_port_db->igs_policer_id = p_vlan_port->igs_policer_id;
    p_vlan_port_db->criteria = p_vlan_port->criteria;
    p_vlan_port_db->gport = p_vlan_port->gport;
    p_vlan_port_db->tunnel_value = p_vlan_port->tunnel_value;
    p_vlan_port_db->fid = p_vlan_port->fid;
    p_vlan_port_db->logic_port = p_vlan_port->logic_port;
    p_vlan_port_db->xlate_nhid = p_vlan_port->xlate_nhid;
    p_vlan_port_db->logic_dest_port = p_vlan_port->logic_dest_port;
    p_vlan_port_db->vn_tag = p_vlan_port->vn_tag;
    p_vlan_port_db->flag = p_vlan_port->flag;
    sal_memcpy(&p_vlan_port_db->igs_vlan_action, &p_vlan_port->igs_vlan_action, sizeof(ctc_scl_vlan_edit_t));
    sal_memcpy(&p_vlan_port_db->egs_vlan_action, &p_vlan_port->egs_vlan_action, sizeof(ctc_scl_vlan_edit_t));

    p_vlan_port_db->p_gem_port_db = p_gem_port_db;

    CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_match_vlan(lchip, p_vlan_port, p_vlan_port_db), ret, roll_back_1);

    /* VLAN edit */
    if (p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN)
    {
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_basic_create(lchip, p_vlan_port, p_vlan_port_db, p_port_db),ret, roll_back_1);
    }
    else
    {
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_flex_create(lchip, p_vlan_port, p_vlan_port_db, p_port_db),ret, roll_back_1);
    }

    if(p_vlan_port->vn_tag)
    {
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_uplink_vn_tag_entry_create(lchip, p_vlan_port_db, p_vlan_port, 0), ret, roll_back_2);
    }

    sys_usw_vlan_set_fid_mapping_vdev_vlan(lchip, p_vlan_port->fid, p_vlan_port->volt_tag, p_vlan_port->volt_tag_valid);

    if(p_gem_port_db)
    {
        sys_usw_nh_add_gem_port_l2edit_8w_outer(lchip, p_vlan_port->logic_port, p_vlan_port->tunnel_value);
    }
    
    p_vlan_port_db->scl_eid = p_vlan_port->scl_eid;
    ctc_hash_insert(p_usw_pon_master[lchip]->vlan_port_hash, p_vlan_port_db);

    if(!CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_PON_SERVICE))
    {
        p_gem_port_db->ref_cnt++;
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT, 1);

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;

roll_back_2:
    if (p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN)
    {
        _sys_usw_pon_vlan_port_basic_destroy(lchip, p_vlan_port_db, p_port_db);
    }
    else
    {
        _sys_usw_pon_vlan_port_flex_destroy(lchip, p_vlan_port_db, p_port_db);
    }

roll_back_1:
    mem_free(p_vlan_port_db);
    p_vlan_port_db = NULL;

roll_back_0:
    SYS_PON_UNLOCK(lchip);

    return ret;
}


#define ___NNI_VLAN_PORT___

int32
_sys_usw_pon_create_nni_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port)
{
    int32 ret = 0;
    uint16 lport = 0;
    sys_pon_port_db_t* p_port_db = NULL;
    sys_pon_vlan_port_db_t* p_vlan_port_db = NULL;
    sys_pon_vlan_port_db_t vlan_port_db_tmp;

    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         p_vlan_port->gport);

    /* CHECK */
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_vlan_port->gport, lchip, lport);
    SYS_PON_SCL_ID_CHECK(p_vlan_port);

    SYS_PON_LOCK(lchip);

    /* DB */
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

    if (0 == p_port_db->enable)
    {
        SYS_PON_UNLOCK(lchip);
       return CTC_E_NOT_READY;
    }

    sal_memset(&vlan_port_db_tmp, 0, sizeof(sys_pon_vlan_port_db_t));
    vlan_port_db_tmp.vlan_port_id = p_vlan_port->vlan_port_id;
    p_vlan_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->vlan_port_hash, &vlan_port_db_tmp);

    if (NULL != p_vlan_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_ENTRY_EXIST;
    }

    if(CTC_WB_ENABLE(lchip) && p_usw_pon_master[lchip]->vlan_port_hash->count >= SYS_WB_PON_VLAN_PORT_NUM)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NO_MEMORY;
    }

    /* Build node */
    MALLOC_PON_POINTER(sys_pon_vlan_port_db_t, p_vlan_port_db);
    if (NULL == p_vlan_port_db)
    {
        goto roll_back_0;
    }

    sal_memset(p_vlan_port_db, 0, sizeof(sys_pon_vlan_port_db_t));
    p_vlan_port_db->vlan_port_id = p_vlan_port->vlan_port_id;
    p_vlan_port_db->criteria = p_vlan_port->criteria;
    p_vlan_port_db->gport = p_vlan_port->gport;
    p_vlan_port_db->fid = p_vlan_port->fid;
    p_vlan_port_db->logic_port = p_vlan_port->logic_port;
    p_vlan_port_db->flag = p_vlan_port->flag;
    

    CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_match_vlan(lchip, p_vlan_port, p_vlan_port_db), ret, roll_back_1);

    if (p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN)
    {
        p_vlan_port_db->scl_id = CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_SCL_ID) ? p_vlan_port->scl_id :
                                 CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_KNOWN_MCAST_SERVICE) ? 1 : 0;
        if (p_vlan_port_db->match_cvlan_end &&  (p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN))
        {
            uint16 match_cvlan = 0;

            for (match_cvlan = p_vlan_port_db->match_cvlan; match_cvlan <=p_vlan_port_db->match_cvlan_end; match_cvlan++)
            {
                CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_add_downlink_scl_entry(lchip,p_port_db->logic_port, match_cvlan, p_vlan_port_db), ret, roll_back_1);
            }
        }
        else
        {
            CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_add_downlink_scl_entry(lchip, p_port_db->logic_port, p_vlan_port_db->match_cvlan, p_vlan_port_db), ret, roll_back_1);
        }
        p_vlan_port->scl_eid = p_vlan_port_db->scl_eid;
    }
    else
    {
        CTC_ERROR_GOTO(_sys_usw_pon_vlan_port_add_downlink_flex(lchip, p_port_db, p_vlan_port), ret, roll_back_1);
        p_vlan_port_db->scl_eid = p_vlan_port->scl_eid;
        p_vlan_port_db->scl_id = CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_SCL_ID)?p_vlan_port->scl_id : 2;
    }
    
    sys_usw_vlan_set_fid_mapping_vdev_vlan(lchip, p_vlan_port->fid, p_vlan_port->volt_tag, p_vlan_port->volt_tag_valid);
    ctc_hash_insert(p_usw_pon_master[lchip]->vlan_port_hash, p_vlan_port_db);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT, 1);

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;

   /*-----------------------------------------------------------
   *** rool back
   -----------------------------------------------------------*/

roll_back_1:
    mem_free(p_vlan_port_db);
    p_vlan_port_db = NULL;

roll_back_0:
    SYS_PON_UNLOCK(lchip);

    return ret;
}

int32
_sys_usw_pon_destroy_uni_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port)
{
    sys_pon_vlan_port_db_t vlan_port_db_tmp;
    sys_pon_vlan_port_db_t* p_vlan_port_db = NULL;
    uint16 lport = 0;
    sys_pon_port_db_t* p_port_db = NULL;

    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_vlan_port);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_vlan_port->gport, lchip, lport);
    SYS_PON_TUNNEL_VLAN_ID_CHECK(p_vlan_port->tunnel_value);

    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         p_vlan_port->gport);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "tunnel_value",         p_vlan_port->tunnel_value);
    SYS_PON_LOCK(lchip);

    /* DB */
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

    if (0 == p_port_db->enable)
    {
        SYS_PON_UNLOCK(lchip);
       return CTC_E_NOT_READY;
    }

    sal_memset(&vlan_port_db_tmp, 0, sizeof(vlan_port_db_tmp));

    vlan_port_db_tmp.vlan_port_id = p_vlan_port->vlan_port_id;
    p_vlan_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->vlan_port_hash, &vlan_port_db_tmp);

    if (NULL == p_vlan_port_db || !(CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_FROM_UNI)) )
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    /* VLAN edit */
    if (p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN)
    {
        _sys_usw_pon_vlan_port_basic_destroy(lchip, p_vlan_port_db, p_port_db);
    }
    else
    {
        _sys_usw_pon_vlan_port_flex_destroy(lchip, p_vlan_port_db, p_port_db);
    }

    if(p_vlan_port_db->vn_tag)
    {
        _sys_usw_pon_vlan_port_uplink_vn_tag_entry_destroy(lchip, p_vlan_port_db);
    }

    ctc_hash_remove(p_usw_pon_master[lchip]->vlan_port_hash, p_vlan_port_db);

    if (0 == p_vlan_port_db->egs_vlan_mapping_en)
    {
        p_vlan_port_db->p_gem_port_db->ref_cnt--;
    }

    /* free memory */
    mem_free(p_vlan_port_db);
    p_vlan_port_db = NULL;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT, 1);

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;
}


int32
_sys_usw_pon_destroy_nni_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port)
{
    sys_pon_vlan_port_db_t vlan_port_db_tmp;
    sys_pon_vlan_port_db_t* p_vlan_port_db = NULL;
    uint16 lport = 0;
    sys_pon_port_db_t* p_port_db = NULL;

    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_vlan_port);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_vlan_port->gport, lchip, lport);
    SYS_PON_TUNNEL_VLAN_ID_CHECK(p_vlan_port->tunnel_value);

    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         p_vlan_port->gport);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "tunnel_value",         p_vlan_port->tunnel_value);
    SYS_PON_LOCK(lchip);

    /* DB */
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

    if (0 == p_port_db->enable)
    {
        SYS_PON_UNLOCK(lchip);
       return CTC_E_NOT_READY;
    }

    sal_memset(&vlan_port_db_tmp, 0, sizeof(vlan_port_db_tmp));

    vlan_port_db_tmp.vlan_port_id = p_vlan_port->vlan_port_id;
    p_vlan_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->vlan_port_hash, &vlan_port_db_tmp);

    if (NULL == p_vlan_port_db || !(CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_FROM_NNI)) || p_vlan_port_db->gport != p_vlan_port->gport )
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    /* VLAN edit */
    if (p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN)
    {
        if (p_vlan_port_db->match_cvlan_end && (p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN))
        {
            uint16 match_cvlan = 0;
            for (match_cvlan = p_vlan_port_db->match_cvlan; match_cvlan <= p_vlan_port_db->match_cvlan_end; match_cvlan++)
            {
                SYS_PON_ERROR_RETURN_UNLOCK(_sys_usw_pon_vlan_port_remove_downlink_scl_entry(lchip, p_port_db->logic_port, match_cvlan,
                                                              p_vlan_port_db));
            }
        }
        else
        {
            SYS_PON_ERROR_RETURN_UNLOCK(_sys_usw_pon_vlan_port_remove_downlink_scl_entry(lchip, p_port_db->logic_port,
                                                           p_vlan_port_db->match_cvlan, p_vlan_port_db));
        }
    }
    else
    {
        _sys_usw_pon_vlan_port_remove_downlink_flex(lchip, p_port_db, p_vlan_port_db);
    }

    ctc_hash_remove(p_usw_pon_master[lchip]->vlan_port_hash, p_vlan_port_db);


    /* free memory */
    mem_free(p_vlan_port_db);
    p_vlan_port_db = NULL;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT, 1);

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;
}

#define ___VLAN_PORT___

int32
_sys_usw_pon_set_default_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port, uint8 is_add)
{
    uint16 lport;
    sys_pon_port_db_t* p_port_db = NULL;
    sys_scl_default_action_t sys_default_action;
    ctc_scl_field_action_t   field_action;
    uint8 index = 0;

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_vlan_port->gport, lchip, lport);

    SYS_PON_LOCK(lchip);
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

    if (0 == p_port_db->enable)
    {
        SYS_PON_UNLOCK(lchip);
       return CTC_E_NOT_READY;
    }

    sal_memset(&sys_default_action, 0, sizeof(sys_scl_default_action_t));
    sal_memset(&field_action, 0, sizeof(field_action));

    sys_default_action.action_type = SYS_SCL_ACTION_INGRESS;
    sys_default_action.lport = lport;
    sys_default_action.field_action = &field_action;

    for (index = 0; index < MCHIP_CAP(SYS_CAP_SCL_HASH_NUM); index++)
    {
        sys_default_action.scl_id = index;
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_PENDING;
        field_action.data0 = 1;
        SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_set_default_action(lchip, &sys_default_action));
        if(is_add)
        {
            field_action.type = CTC_SCL_FIELD_ACTION_TYPE_FID;
            field_action.data0 = p_vlan_port->fid;
            SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_set_default_action(lchip, &sys_default_action));
            if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FROM_NNI))
            {
                field_action.type = CTC_SCL_FIELD_ACTION_TYPE_DENY_LEARNING;
                SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_set_default_action(lchip, &sys_default_action));
            }
            if(p_usw_pon_master[lchip]->pon_mode && DRV_FROM_TMM(lchip))
            {
                field_action.type = CTC_SCL_FIELD_ACTION_TYPE_CANCEL_LKUP_BMP;
                field_action.data0 = 0x2;
                SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_set_default_action(lchip, &sys_default_action));
            }
        }
        field_action.type = CTC_SCL_FIELD_ACTION_TYPE_PENDING;
        field_action.data0 = 0;
        SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_set_default_action(lchip, &sys_default_action));
    }
    if(is_add)
    {
        sys_usw_vlan_set_fid_mapping_vdev_vlan(lchip, p_vlan_port->fid, p_vlan_port->volt_tag, p_vlan_port->volt_tag_valid);
    }
    SYS_PON_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_pon_destroy_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port)
{
    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_vlan_port);

    if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_DEFAULT_SERVICE))
    {
        CTC_ERROR_RETURN(_sys_usw_pon_set_default_vlan_port(lchip, p_vlan_port, 0))
    }
    else if (CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FROM_UNI))
    {
        CTC_ERROR_RETURN(_sys_usw_pon_destroy_uni_vlan_port(lchip, p_vlan_port));
    }
    else if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FROM_NNI))
    {
        CTC_ERROR_RETURN(_sys_usw_pon_destroy_nni_vlan_port(lchip, p_vlan_port));
    }
    else
    {
        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [PON] Invalid para , line:%d\n", __LINE__);
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;


}

int32
sys_usw_pon_update_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port)
{
    uint32 vlan_mapping_port = 0;
    uint16 lport = 0;
    sys_pon_vlan_port_db_t vlan_port_db_tmp;
    sys_pon_vlan_port_db_t* p_vlan_port_db = NULL;
    sys_pon_port_db_t* p_port_db = NULL;
    ctc_qos_policer_t policer;
    ctc_vlan_mapping_t vlan_mapping;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;
    ctc_scl_field_action_t field_action;

    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_vlan_port);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_vlan_port->gport, lchip, lport);
    SYS_PON_TUNNEL_VLAN_ID_CHECK(p_vlan_port->tunnel_value);

    /* Debug */
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         p_vlan_port->gport);
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "tunnel_value",         p_vlan_port->tunnel_value);
    if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_DEFAULT_SERVICE))
    {
        CTC_ERROR_RETURN(_sys_usw_pon_set_default_vlan_port(lchip, p_vlan_port, 1));
    }
    SYS_PON_LOCK(lchip);
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

    if (0 == p_port_db->enable)
    {
        SYS_PON_UNLOCK(lchip);
       return CTC_E_NOT_READY;
    }

    /* DB */
    sal_memset(&vlan_port_db_tmp, 0, sizeof(vlan_port_db_tmp));
    sal_memset(&policer, 0, sizeof(policer));

    vlan_port_db_tmp.vlan_port_id = p_vlan_port->vlan_port_id;
    p_vlan_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->vlan_port_hash, &vlan_port_db_tmp);

    if (NULL == p_vlan_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    /*-----------------------------------------*/
    /*Ingress policetr*/
    if (CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FID) || CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_IGS_POLICER))
    {
        if ((p_vlan_port->igs_policer_id == p_vlan_port_db->igs_policer_id) && CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_IGS_POLICER))
        {
            SYS_PON_UNLOCK(lchip);
            return CTC_E_NONE;
        }

        p_gem_port_db = p_vlan_port_db->p_gem_port_db;

        /* Add vlan mapping */
        sal_memset(&vlan_mapping, 0, sizeof(vlan_mapping));

        if (( p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN ) && 
                (DRV_IS_TSINGMA(lchip) || (DRV_FROM_TMM(lchip) && !p_vlan_port_db->match_svlan_end)))
        {
            if (0 == p_vlan_port_db->egs_vlan_mapping_en )
            {
                uint32 tmp_logic_port = (CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_FROM_NNI)) ? p_port_db->logic_port : 
                                         p_vlan_port_db->acl_logic_port ? p_vlan_port_db->acl_logic_port : p_gem_port_db->logic_port;
                vlan_mapping.flag = CTC_VLAN_MAPPING_FLAG_USE_LOGIC_PORT;
                vlan_mapping_port = tmp_logic_port;
            }
            else
            {
                vlan_mapping_port = p_vlan_port_db->gport;
            }
            vlan_mapping.scl_id = p_vlan_port_db->scl_id;

            SYS_PON_SET_VLANMAPPING_KEY_TYPE();
            
            /* Add vlan range */
            if (p_vlan_port_db->match_svlan_end)
            {
                vlan_mapping.svlan_end = p_vlan_port_db->match_svlan_end;
                vlan_mapping.vrange_grpid = p_port_db->vlan_range_grp;
                CTC_SET_FLAG(vlan_mapping.flag, CTC_VLAN_MAPPING_FLAG_USE_FLEX);
            }

            SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_vlan_get_vlan_mapping(lchip, vlan_mapping_port , &vlan_mapping));

            if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FID))
            {
                vlan_mapping.u3.fid = p_vlan_port->fid;
            }
            if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_IGS_POLICER))
            {
                vlan_mapping.policer_id = p_vlan_port->igs_policer_id;
            }

            SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_vlan_update_vlan_mapping(lchip, vlan_mapping_port , &vlan_mapping));
        }
        else
        {
             if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_IGS_POLICER))
            {
                sal_memset(&field_action, 0, sizeof(field_action));
                field_action.type = CTC_SCL_FIELD_ACTION_TYPE_POLICER_ID;
                field_action.data0 = p_vlan_port->igs_policer_id;
                field_action.data1 = 1;
                if (p_vlan_port->igs_policer_id)
                {
                    SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_add_action_field(lchip, ENCODE_SCL_UPLINK_ENTRY_ID(p_vlan_port_db->vlan_port_id, 0), &field_action));
                }
                else
                {
                    SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_remove_action_field(lchip, ENCODE_SCL_UPLINK_ENTRY_ID(p_vlan_port_db->vlan_port_id, 0), &field_action));
                }
            }
             if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FID))
            {
                uint32 entry_id = (CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_FROM_NNI)) ? 
                                  ENCODE_SCL_VLAN_ENTRY_ID(p_vlan_port_db->vlan_port_id): ENCODE_SCL_UPLINK_ENTRY_ID(p_vlan_port_db->vlan_port_id, 0);
                sal_memset(&field_action, 0, sizeof(field_action));
                field_action.type = CTC_SCL_FIELD_ACTION_TYPE_FID;
                field_action.data0 = p_vlan_port->fid;
                field_action.data1 = 0;
                if (p_vlan_port->fid)
                {
                    SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_add_action_field(lchip, entry_id, &field_action));
                }
                else
                {
                    SYS_PON_ERROR_RETURN_UNLOCK(sys_usw_scl_remove_action_field(lchip, entry_id, &field_action));
                }
            }

        }
        if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FID))
        {
            sys_usw_vlan_set_fid_mapping_vdev_vlan(lchip, p_vlan_port->fid, p_vlan_port->volt_tag, p_vlan_port->volt_tag_valid);
            p_vlan_port_db->fid  = p_vlan_port->fid;
        }
        if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_IGS_POLICER))
        {
            p_vlan_port_db->igs_policer_id  = p_vlan_port->igs_policer_id;
        }
    }

    if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_VN_TAG))
    {
        if(p_vlan_port->vn_tag > CTC_MAX_VLAN_ID)
        {
            SYS_PON_UNLOCK(lchip);
            SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [PON] p_vlan_port->vn_tag is %d , line:%d\n", p_vlan_port->vn_tag, __LINE__);
            return CTC_E_INVALID_PARAM;
        }
        SYS_PON_ERROR_RETURN_UNLOCK(_sys_usw_pon_update_vlan_port_vn_tag(lchip, p_vlan_port_db, p_vlan_port));
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT, 1);

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_pon_create_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port)
{
    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_vlan_port);

    if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_DEFAULT_SERVICE))
    {
        CTC_ERROR_RETURN(_sys_usw_pon_set_default_vlan_port(lchip, p_vlan_port, 1))
    }
    else if (CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FROM_UNI))
    {
        CTC_ERROR_RETURN(_sys_usw_pon_create_uni_vlan_port(lchip, p_vlan_port));
    }
    else if(CTC_FLAG_ISSET(p_vlan_port->flag, CTC_PON_VLAN_PORT_FLAG_FROM_NNI))
    {
        CTC_ERROR_RETURN(_sys_usw_pon_create_nni_vlan_port(lchip, p_vlan_port));
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;

}

int32
sys_usw_pon_get_vlan_port(uint8 lchip, ctc_pon_vlan_port_t* p_vlan_port)
{
    sys_pon_vlan_port_db_t vlan_port_db_tmp;
    sys_pon_vlan_port_db_t* p_vlan_port_db = NULL;

    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_vlan_port);

    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "vlan_port_id",         p_vlan_port->vlan_port_id);

    SYS_PON_LOCK(lchip);

    /* DB */
    sal_memset(&vlan_port_db_tmp, 0, sizeof(vlan_port_db_tmp));

    vlan_port_db_tmp.vlan_port_id = p_vlan_port->vlan_port_id;
    p_vlan_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->vlan_port_hash, &vlan_port_db_tmp);

    if (NULL == p_vlan_port_db)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    p_vlan_port->logic_port = p_vlan_port_db->logic_port;
    p_vlan_port->vlan_port_id = p_vlan_port_db->vlan_port_id;
    p_vlan_port->igs_policer_id = p_vlan_port_db->igs_policer_id;
    p_vlan_port->criteria = p_vlan_port_db->criteria;
    p_vlan_port->gport = p_vlan_port_db->gport;
    p_vlan_port->tunnel_value = p_vlan_port_db->tunnel_value;
    p_vlan_port->fid = p_vlan_port_db->fid;
    p_vlan_port->logic_port = p_vlan_port_db->logic_port;
    p_vlan_port->xlate_nhid = p_vlan_port_db->xlate_nhid;
    p_vlan_port->scl_eid = p_vlan_port_db->scl_eid;
    p_vlan_port->scl_id = p_vlan_port_db->scl_id;
    sal_memcpy(&p_vlan_port->igs_vlan_action, &p_vlan_port_db->igs_vlan_action, sizeof(ctc_scl_vlan_edit_t));
    sal_memcpy(&p_vlan_port->egs_vlan_action, &p_vlan_port_db->egs_vlan_action, sizeof(ctc_scl_vlan_edit_t));

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;
}

#define ___NETWORK_PORT__________
/*Network port*/
int32
_sys_usw_pon_set_gem_port_en(uint8 lchip, uint32 gport, uint32 enable)
{
    uint32 chan_id = 0;
    int32 ret = 0;
    uint32 cmd = 0;
    uint32 field_val = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    /* cfg mux type */
    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (!SYS_IS_NETWORK_CHANNEL(chan_id))
    {
        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [PON] chan_id is %d  , line:%d\n",chan_id, __LINE__);
        return CTC_E_INVALID_PORT;
    }

    field_val =  enable?6:0;  /*   EPE_IGS_MUXTYPE_GEM_PORT = 6,*/
    cmd = DRV_IOW(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_muxType_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));

    return ret;
}

int32
sys_usw_pon_set_uni_en(uint8 lchip, uint32 gport, ctc_pon_port_cfg_t* cfg)
{
    int32 ret = 0;
    uint16 lport = 0;
    uint32 chan_id = 0xFF;
    uint8 igs_hash_type = 0;
    uint8 egs_hash_type = 0;
    uint8 is_internal = 0;
    sys_pon_port_db_t* p_port_db = NULL;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    ctc_port_scl_property_t scl_prop;

    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (!SYS_IS_NETWORK_CHANNEL(chan_id))
    {
        is_internal = 1;
    }

    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         gport);

    SYS_PON_LOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT, 1);
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

    if (cfg->value == p_port_db->enable)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NONE;
    }
    if(p_usw_pon_master[lchip]->pon_mode != 2)
    {
    /***********************************************/
    /** Enable scl lookup double vlan for onu and pon qinq */
    if(cfg->criteria== CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN)
    {
        igs_hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_2VLAN;
        egs_hash_type = CTC_PORT_EGS_SCL_HASH_TYPE_PORT_2VLAN;
    }
    else
    {
        igs_hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_SVLAN;
        egs_hash_type = CTC_PORT_EGS_SCL_HASH_TYPE_PORT_SVLAN;
    }

    sal_memset(&scl_prop, 0, sizeof(scl_prop));
    scl_prop.scl_id = p_usw_pon_master[lchip]->pon_mode ? 1 : 0;
    scl_prop.direction = CTC_INGRESS;
    scl_prop.hash_type = cfg->value? igs_hash_type : CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
    scl_prop.use_logic_port_en = 1;
    scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
    scl_prop.tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_RESOLVE_CONFLICT;
    scl_prop.hash_vlan_range_dis = 1;
    CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip, gport, &scl_prop), ret, roll_back_0);

    sal_memset(&scl_prop, 0, sizeof(scl_prop));
    scl_prop.direction = CTC_INGRESS;
    scl_prop.tcam_type = CTC_PORT_IGS_SCL_TCAM_TYPE_RESOLVE_CONFLICT;
    scl_prop.hash_vlan_range_dis = 1;
    if(p_usw_pon_master[lchip]->pon_mode)
    {
        scl_prop.scl_id = 0;
        scl_prop.hash_type = cfg->value? CTC_PORT_IGS_SCL_HASH_TYPE_L2 : CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
        scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_FLOW;
        CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_SCL_HASH_FIELD_SEL_ID, 3), ret, roll_back_0);
    }
    else
    {
        scl_prop.scl_id = 1;
        scl_prop.hash_type =  cfg->value? igs_hash_type : CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
        scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
    }
    CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip, gport, &scl_prop), ret, roll_back_0);

    /***********************************************/
    /** Enable egress scl lookup double vlan for pon service do vlan xlate*/
    sal_memset(&scl_prop, 0, sizeof(scl_prop));
    scl_prop.scl_id = 0;
    scl_prop.direction = CTC_EGRESS;
    scl_prop.hash_type = cfg->value? egs_hash_type : CTC_PORT_EGS_SCL_HASH_TYPE_DISABLE;
    scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
    CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip, gport, &scl_prop), ret, roll_back_0);

    /***********************************************/
    /** Uni port property*/
    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_PORT_EN, cfg->value?1:0), ret, roll_back_0);
    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_UNTAG_PVID_TYPE,
                   cfg->value?CTC_PORT_UNTAG_PVID_TYPE_NONE: CTC_PORT_UNTAG_PVID_TYPE_SVLAN), ret, roll_back_0);
    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_LEARNING_EN, cfg->value?1:0), ret, roll_back_0);
    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_SCL_USE_DEFAULT_LOOKUP, cfg->value?0:1), ret, roll_back_0);
    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_ADD_DEFAULT_VLAN_DIS, cfg->value?1:0), ret, roll_back_0);

    if (DRV_FROM_TMM(lchip))
    {
        sal_memset(&scl_prop, 0, sizeof(scl_prop));
        scl_prop.scl_id = 2;
        scl_prop.direction = CTC_INGRESS;
        scl_prop.use_logic_port_en = cfg->value?1:0;
        scl_prop.tcam_type = cfg->value? CTC_PORT_IGS_SCL_TCAM_TYPE_IP:CTC_PORT_IGS_SCL_TCAM_TYPE_DISABLE;
        CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip,gport, &scl_prop), ret, roll_back_0);
        sal_memset(&scl_prop, 0, sizeof(scl_prop));
        scl_prop.scl_id = 3;
        scl_prop.direction = CTC_INGRESS;
        scl_prop.use_logic_port_en = 0;
        scl_prop.tcam_type = cfg->value? CTC_PORT_IGS_SCL_TCAM_TYPE_IP:CTC_PORT_IGS_SCL_TCAM_TYPE_DISABLE;
        CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip,gport, &scl_prop), ret, roll_back_0);
        CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip,gport, CTC_PORT_PROP_SELECT_MAX_SCL_PRIO_EN, p_usw_pon_master[lchip]->pon_mode ? (!cfg->value) : cfg->value), ret, roll_back_0);
    }
    if (0 == cfg->value)
    {
        _sys_usw_pon_vlan_range_group_en(lchip, gport, CTC_MAX_UINT8_VALUE);
    }
    if(is_internal)
    {
        p_port_db->enable = cfg->value;
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NONE;
    }
    }
    /***********************************************/
    /** enable uni port mux gem */
    CTC_ERROR_GOTO(_sys_usw_pon_set_gem_port_en(lchip, gport, cfg->value), ret, roll_back_0);

    /***********************************************/

    p_port_db->enable = cfg->value;

    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;

roll_back_0:
    SYS_PON_UNLOCK(lchip);
    return ret;
}

/*Network port*/
int32
sys_usw_pon_set_nni_en(uint8 lchip, uint32 gport, ctc_pon_port_cfg_t* cfg)
{
    int32 ret = 0;
    uint8 hash_type = 0;
    uint16 lport = 0;
    ctc_port_scl_property_t scl_prop;
    sys_pon_port_db_t* p_port_db = NULL;

    /* CHECK */
    SYS_PON_INIT_CHECK(lchip);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);

    /* Debug */
    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "port", gport);

    SYS_PON_LOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT, 1);
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];

    if (cfg->value == p_port_db->enable)
    {
        SYS_PON_UNLOCK(lchip);
        return CTC_E_NONE;
    }

    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_UNTAG_PVID_TYPE,
                   cfg->value? CTC_PORT_UNTAG_PVID_TYPE_NONE: CTC_PORT_UNTAG_PVID_TYPE_SVLAN), ret, roll_back_0);
    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_ADD_DEFAULT_VLAN_DIS, cfg->value?1:0), ret, roll_back_0);
    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_SCL_USE_DEFAULT_LOOKUP, cfg->value?0:1), ret, roll_back_0);
    CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_LOGIC_PORT_CHECK_EN, cfg->value?1:0), ret, roll_back_0);

    if(cfg->criteria== CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN)
    {
        hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_2VLAN;
    }
    else
    {
        hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_SVLAN;
    }

    sal_memset(&scl_prop, 0, sizeof(scl_prop));
    scl_prop.scl_id = 0;
    scl_prop.direction = CTC_INGRESS;
    scl_prop.hash_type = cfg->value?hash_type : CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
    scl_prop.tcam_type = cfg->value?CTC_PORT_IGS_SCL_TCAM_TYPE_RESOLVE_CONFLICT : CTC_PORT_IGS_SCL_TCAM_TYPE_DISABLE;
    scl_prop.use_logic_port_en = 1;
    scl_prop.hash_mcast_dis = CTC_FLAG_ISSET(cfg->flag, CTC_PON_PORT_FLAG_DIS_UNKNOWN_MCAST_LOOKUP);
    scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
    CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip, gport, &scl_prop), ret, roll_back_0);

    sal_memset(&scl_prop, 0, sizeof(scl_prop));
    scl_prop.scl_id = 0;
    scl_prop.direction = CTC_EGRESS;
    scl_prop.hash_type = cfg->value?CTC_PORT_EGS_SCL_HASH_TYPE_PORT_XC : CTC_PORT_EGS_SCL_HASH_TYPE_DISABLE;
    scl_prop.use_logic_port_en = 1;
    CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip, gport, &scl_prop), ret, roll_back_0);

    sal_memset(&scl_prop, 0, sizeof(scl_prop));
    scl_prop.scl_id = 1;
    scl_prop.direction = CTC_INGRESS;
    scl_prop.hash_type = cfg->value? hash_type: CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
    scl_prop.tcam_type = cfg->value? CTC_PORT_IGS_SCL_TCAM_TYPE_RESOLVE_CONFLICT : CTC_PORT_IGS_SCL_TCAM_TYPE_DISABLE;
    scl_prop.use_logic_port_en = 1;
    scl_prop.hash_mcast_dis = 0;
    scl_prop.action_type = CTC_PORT_SCL_ACTION_TYPE_SCL;
    CTC_ERROR_GOTO(sys_usw_port_api_set_scl_property(lchip, gport, &scl_prop), ret, roll_back_0);

    CTC_ERROR_GOTO(sys_usw_bpe_port_vdev_en(lchip, gport, cfg->value?1:0), ret, roll_back_0);

    p_port_db->enable = cfg->value;

    SYS_PON_UNLOCK(lchip);
    return CTC_E_NONE;

roll_back_0:

    SYS_PON_UNLOCK(lchip);

    return ret;
}


/*Network port*/
int32
sys_usw_pon_set_port_propery(uint8 lchip, uint32 gport, ctc_pon_port_cfg_t* cfg)
{
    uint16 lport = 0;
    sys_pon_port_db_t* p_port_db = NULL;

    CTC_PTR_VALID_CHECK(cfg);
    SYS_PON_INIT_CHECK(lchip);

    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         gport);

    switch(cfg->type)
    {
        case CTC_PON_PORT_CFG_UNI_EN:
            CTC_ERROR_RETURN(sys_usw_pon_set_uni_en(lchip, gport, cfg));
            break;
        case CTC_PON_PORT_CFG_NNI_EN:
            CTC_ERROR_RETURN(sys_usw_pon_set_nni_en(lchip, gport, cfg));
            break;
        case CTC_PON_PORT_CFG_NNI_LOGIC_PORT:
            SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);
            CTC_ERROR_RETURN(sys_usw_port_api_set_property(lchip, gport, CTC_PORT_PROP_LOGIC_PORT, cfg->value));
            SYS_PON_LOCK(lchip);
            SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT, 1);
            p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];
            p_port_db->logic_port = cfg->value;
            SYS_PON_UNLOCK(lchip);
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }
    return CTC_E_NONE;
}

int32
sys_usw_pon_get_port_propery(uint8 lchip, uint32 gport, ctc_pon_port_cfg_t* cfg)
{
    uint16 lport = 0;
    sys_pon_port_db_t* p_port_db = NULL;

    CTC_PTR_VALID_CHECK(cfg);
    SYS_PON_INIT_CHECK(lchip);

    SYS_PON_DBG_FUNC();
    SYS_PON_DBG_PARAM("-------------------------------------------------\n");
    SYS_PON_DBG_PARAM("%-40s :%10u\n", "gport",         gport);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);

    SYS_PON_LOCK(lchip);
    p_port_db = &p_usw_pon_master[lchip]->p_port_db[lport];
    switch(cfg->type)
    {
        case CTC_PON_PORT_CFG_UNI_EN:
        case CTC_PON_PORT_CFG_NNI_EN:
            cfg->value = p_port_db->enable;
            break;
        case CTC_PON_PORT_CFG_NNI_LOGIC_PORT:
            cfg->value  = p_port_db->logic_port;
            break;
        default:
            SYS_PON_UNLOCK(lchip);
            return CTC_E_INVALID_PARAM;
    }
    SYS_PON_UNLOCK(lchip);
    return CTC_E_NONE;
}


int32
sys_usw_pon_init_scl_lookup(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 ad_mask[6] = {0};
    uint32 mimicryctl[8];
    uint32 ipe_hdr_rsv;

    if(SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A && DRV_IS_TSINGMA(lchip))
    {
        sal_memset(mimicryctl, 0, sizeof(mimicryctl));
        CTC_BMP_SET(ad_mask, 1 + 64); /*USERIDHASHTYPE_DOUBLEVLANPORT*/
        CTC_BMP_SET(ad_mask,  0x38); /*USERIDHASHTYPE_SCLFLOWL2*/
        CTC_BMP_SET(ad_mask, 128);
        CTC_BMP_SET(ad_mask, 129);
        CTC_BMP_SET(ad_mask, 130);
        CTC_BMP_SET(ad_mask, 132);

        SetIpeUserIdMimicryCtl(A, mimicrySclAdMask_f, mimicryctl, ad_mask);
        cmd = DRV_IOW(IpeUserIdMimicryCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, mimicryctl));

        cmd = DRV_IOR(IpeHdrAdjReserved_t, IpeHdrAdjReserved_reserved_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &ipe_hdr_rsv));
        ipe_hdr_rsv |= ((1<<1)|(1<<8)|(1<<9));
        cmd = DRV_IOW(IpeHdrAdjReserved_t, IpeHdrAdjReserved_reserved_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &ipe_hdr_rsv));
    }
    
    return CTC_E_NONE;
}

#define __WARMBOOT__

int32
_sys_usw_pon_gem_port_sync_func(void* bucket_data, void* user_data)
{
    uint32 max_entry_cnt = 0;
    uint8 lchip = 0;
    uint8 gchip_id = 0;
    
    ctc_wb_data_t* p_wb_data = (ctc_wb_data_t*) user_data;
    sys_pon_gem_port_db_t* p_gem_port_db = (sys_pon_gem_port_db_t*) bucket_data;
    sys_wb_pon_gem_port_db_t* p_wb_gem_port_db = NULL;

    max_entry_cnt = p_wb_data->buffer_len/ sizeof(sys_wb_pon_gem_port_db_t);
    p_wb_gem_port_db = (sys_wb_pon_gem_port_db_t*) p_wb_data->buffer + p_wb_data->valid_cnt;
    p_wb_gem_port_db->lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_gem_port_db->gport);
    p_wb_gem_port_db->tunnel_value = p_gem_port_db->tunnel_value;
    if(p_gem_port_db->is_flooding)
    {
        p_wb_gem_port_db->lport |= 0x1 << 15;
    }
    else
    {
        gchip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(p_gem_port_db->gport);
        CTC_ERROR_RETURN(sys_usw_get_local_chip_id(gchip_id, &lchip));
        CTC_ERROR_RETURN(_sys_pon_get_gem_port_hw_index(lchip, p_gem_port_db, &p_wb_gem_port_db->hw_tbl_index));    
    }
    p_wb_gem_port_db->egs_service_id = p_gem_port_db->egs_service_id;
    p_wb_gem_port_db->igs_policer_id = p_gem_port_db->igs_policer_id;
    if (++p_wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(p_wb_data));
        p_wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_pon_vlan_port_sync_func(void* bucket_data, void* user_data)
{
    uint32 max_entry_cnt = 0;
    ctc_wb_data_t* p_wb_data = (ctc_wb_data_t*) user_data;
    sys_pon_vlan_port_db_t* p_vlan_port_db = (sys_pon_vlan_port_db_t*) bucket_data;
    sys_wb_pon_vlan_port_t* p_wb_vlan_port_db = NULL;

    max_entry_cnt = p_wb_data->buffer_len/ sizeof(sys_wb_pon_vlan_port_t);
    p_wb_vlan_port_db = (sys_wb_pon_vlan_port_t*) p_wb_data->buffer + p_wb_data->valid_cnt;
    p_wb_vlan_port_db->vlan_port_id = p_vlan_port_db->vlan_port_id;
    p_wb_vlan_port_db->criteria = p_vlan_port_db->criteria;
    p_wb_vlan_port_db->flag = p_vlan_port_db->flag;
    p_wb_vlan_port_db->lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_vlan_port_db->gport);
    p_wb_vlan_port_db->tunnel_value = p_vlan_port_db->tunnel_value;    
    p_wb_vlan_port_db->logic_port = p_vlan_port_db->logic_port;    
    p_wb_vlan_port_db->logic_dest_port = p_vlan_port_db->logic_dest_port;    
    p_wb_vlan_port_db->acl_logic_port = p_vlan_port_db->acl_logic_port;
    p_wb_vlan_port_db->xlate_nhid = p_vlan_port_db->xlate_nhid;
    p_wb_vlan_port_db->scl_eid = p_vlan_port_db->scl_eid;

    p_wb_vlan_port_db->match_svlan_end = p_vlan_port_db->match_svlan_end;
    p_wb_vlan_port_db->match_cvlan_end = p_vlan_port_db->match_cvlan_end;
    p_wb_vlan_port_db->vn_tag = p_vlan_port_db->vn_tag;    
    sal_memcpy(&p_wb_vlan_port_db->egs_vlan_action, &p_vlan_port_db->egs_vlan_action, sizeof(ctc_scl_vlan_edit_t));
    
    if (++p_wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(p_wb_data));
        p_wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
sys_usw_pon_wb_sync(uint8 lchip, uint32 app_id)
{
    int32 ret = CTC_E_NONE;
    ctc_wb_data_t wb_data = {0};
    int16 lport = 0;
    sys_wb_pon_port_db_t* p_wb_port_db = NULL;

    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    SYS_PON_LOCK(lchip);

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_PON_SUBID_PORT)
    {
        /*for different kinds of data stored, the wb_data must be reinited*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_pon_gem_port_db_t, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT);
        for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PORT_NUM); lport++)
        {
            if(p_usw_pon_master[lchip]->p_port_db[lport].enable)
            {
                p_wb_port_db = (sys_wb_pon_port_db_t*) wb_data.buffer + wb_data.valid_cnt++;
                p_wb_port_db->lport = lport;
                p_wb_port_db->vlan_range_grp = p_usw_pon_master[lchip]->p_port_db[lport].vlan_range_grp;
                p_wb_port_db->vlan_range_grp_cnt = p_usw_pon_master[lchip]->p_port_db[lport].vlan_range_grp_cnt;
            }
        }
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT);
    }
    
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_PON_SUBID_GEM_PORT)
    {
        /*for different kinds of data stored, the wb_data must be reinited*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_pon_gem_port_db_t, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_GEM_PORT);
        CTC_ERROR_GOTO(ctc_hash_traverse(p_usw_pon_master[lchip]->gem_port_hash, _sys_usw_pon_gem_port_sync_func, (void*)(&wb_data)), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_GEM_PORT);
    }

    if (p_usw_pon_master[lchip]->vlan_port_hash && (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_PON_SUBID_VLAN_PORT))
    {
        /*for different kinds of data stored, the wb_data must be reinited*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_pon_vlan_port_t, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT);
        CTC_ERROR_GOTO(ctc_hash_traverse(p_usw_pon_master[lchip]->vlan_port_hash, _sys_usw_pon_vlan_port_sync_func, (void*)(&wb_data)), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT);
    }
    
done:
    SYS_PON_UNLOCK(lchip);
    CTC_WB_FREE_BUFFER(wb_data.buffer);
    return ret;
}

int32
sys_usw_pon_wb_restore(uint8 lchip)
{
    uint32 entry_cnt = 0;
    int32 ret = CTC_E_NONE;
    ctc_wb_query_t wb_query;
    sys_pon_gem_port_db_t* p_gem_port_db = NULL;   
    sys_pon_gem_port_db_t gem_port_db = {0};
    sys_wb_pon_gem_port_db_t wb_gem_port_db = {0};
    sys_pon_vlan_port_db_t* p_vlan_port_db = NULL;
    sys_wb_pon_vlan_port_t wb_vlan_port_db = {0};
    sys_wb_pon_port_db_t  wb_port = {0};
    uint8 gchip = 0;
    uint16 lport = 0;
    ctc_scl_entry_t scl_entry = {0};
    ctc_field_key_t  field_key = {0};
    ctc_scl_field_action_t scl_action = {0};
    uint32 value = 0;
    sys_usw_opf_t opf;

    sys_usw_get_gchip_id(lchip, &gchip);

    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);
    
    /*port*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_pon_port_db_t, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT);
    sal_memset(&wb_port, 0, sizeof(sys_wb_pon_port_db_t));
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
    sal_memcpy((uint8*)&wb_port, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
    entry_cnt++;
    lport = wb_port.lport;
    p_usw_pon_master[lchip]->p_port_db[lport].vlan_range_grp = wb_port.vlan_range_grp;
    
    CTC_ERROR_GOTO(sys_usw_port_api_get_property(lchip, SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip,lport), CTC_PORT_PROP_SCL_USE_DEFAULT_LOOKUP, &value), ret, done);
    p_usw_pon_master[lchip]->p_port_db[lport].enable = !value;
    CTC_ERROR_GOTO(sys_usw_port_api_get_property(lchip,
                                                SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, lport), 
                                                CTC_PORT_PROP_LOGIC_PORT,
                                                &value), ret, done);
    p_usw_pon_master[lchip]->p_port_db[lport].logic_port = value;
    p_usw_pon_master[lchip]->p_port_db[lport].vlan_range_grp_cnt = wb_port.vlan_range_grp_cnt;
    if(0xFF != wb_port.vlan_range_grp)
    {
        sal_memset(&opf, 0, sizeof(opf));
        opf.pool_type = p_usw_pon_master[lchip]->opf_vlan_range_group_id;
        opf.pool_index = 0;
        CTC_ERROR_GOTO(sys_usw_opf_alloc_offset_from_position(lchip, &opf, 1, wb_port.vlan_range_grp), ret, done);
    }
    CTC_WB_QUERY_ENTRY_END((&wb_query));
    
    /*gem port*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_pon_gem_port_db_t, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_GEM_PORT);
    sal_memset(&wb_gem_port_db, 0, sizeof(sys_wb_pon_gem_port_db_t));
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
    sal_memcpy((uint8*)&wb_gem_port_db, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
    entry_cnt++;
    p_gem_port_db = mem_malloc(MEM_PON_MODULE, sizeof(sys_pon_gem_port_db_t));
    if (NULL == p_gem_port_db)
    {
        ret = CTC_E_NO_MEMORY;
        goto done;
    }
    sal_memset(p_gem_port_db, 0, sizeof(sys_pon_gem_port_db_t));
    p_gem_port_db->gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip,(wb_gem_port_db.lport & 0xEFFF));
    p_gem_port_db->tunnel_value = wb_gem_port_db.tunnel_value;
    p_gem_port_db->igs_policer_id = wb_gem_port_db.igs_policer_id;
    if(wb_gem_port_db.lport >> 15)/*flooding gemport*/
    {
        p_gem_port_db->logic_port = wb_gem_port_db.egs_service_id;
        p_gem_port_db->is_flooding = 1;
    }
    else
    {
        drv_acc_in_t in;
        drv_acc_out_t out;

        p_gem_port_db->egs_service_id = wb_gem_port_db.egs_service_id;

        sal_memset(&in, 0, sizeof(in));
        sal_memset(&out, 0, sizeof(out));
        in.type = DRV_ACC_TYPE_LOOKUP;
        in.op_type = DRV_ACC_OP_BY_INDEX;
        in.tbl_id    = DsGemPortHashKey_t;
        in.index     = wb_gem_port_db.hw_tbl_index;
        in.module = DRV_ACC_HASH_MODULE_GEMPORT_HASH;
        CTC_ERROR_GOTO(drv_acc_api(lchip, &in, &out), ret, done);

        p_gem_port_db->logic_port = GetDsGemPortHashKey (V, logicSrcPort_f, out.data);
        p_gem_port_db->pass_through_en = !(GetDsGemPortHashKey (V, onuPassThroughEn_f, out.data));
        if(GetDsGemPortHashKey (V, macSecurityExceptionEn_f, out.data))
        {
           p_gem_port_db->mac_security = CTC_MACLIMIT_ACTION_TOCPU;
        }
    }

    ctc_hash_insert(p_usw_pon_master[lchip]->gem_port_hash, (void*)(p_gem_port_db));    
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*vlan port*/
    if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_SCL))
    {
        CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_pon_vlan_port_t, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT);
        /* set default value to new added fields, default value may not be zeros */
        sal_memset(&wb_vlan_port_db, 0, sizeof(sys_wb_pon_vlan_port_t));
        CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)&wb_vlan_port_db, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;
        p_vlan_port_db = mem_malloc(MEM_PON_MODULE, sizeof(sys_pon_vlan_port_db_t));
        if (NULL == p_vlan_port_db)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(p_vlan_port_db, 0, sizeof(sys_pon_vlan_port_db_t));
        p_vlan_port_db->vlan_port_id        = wb_vlan_port_db.vlan_port_id;    
        p_vlan_port_db->criteria            = wb_vlan_port_db.criteria;
        p_vlan_port_db->flag                = wb_vlan_port_db.flag;
        p_vlan_port_db->gport               = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip,wb_vlan_port_db.lport);
        p_vlan_port_db->tunnel_value        = wb_vlan_port_db.tunnel_value;
       
        p_vlan_port_db->match_svlan_end     = wb_vlan_port_db.match_svlan_end;
        p_vlan_port_db->match_cvlan_end     = wb_vlan_port_db.match_cvlan_end;

        p_vlan_port_db->vn_tag              = wb_vlan_port_db.vn_tag;
        p_vlan_port_db->logic_port          = wb_vlan_port_db.logic_port;
        p_vlan_port_db->logic_dest_port     = wb_vlan_port_db.logic_dest_port;
        p_vlan_port_db->acl_logic_port      = wb_vlan_port_db.acl_logic_port;
        p_vlan_port_db->xlate_nhid          = wb_vlan_port_db.xlate_nhid;
        p_vlan_port_db->scl_eid             = wb_vlan_port_db.scl_eid; 
        p_vlan_port_db->scl_id             = wb_vlan_port_db.scl_id;

        if (CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_PON_SERVICE) && CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_FROM_UNI))
        {
            p_vlan_port_db->egs_vlan_mapping_en = 1;
        }

        if (CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_PASS_THROUGH))
        {
            p_vlan_port_db->pass_through_en = 1;
        }
        
        if(CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_FROM_NNI))
        {
            if(p_vlan_port_db->scl_eid)
            {
                scl_entry.entry_id = p_vlan_port_db->scl_eid;
                if (p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN)
                {
                    CTC_ERROR_GOTO(sys_usw_scl_get_entry_by_id(lchip, &scl_entry),ret, done);
                    switch(scl_entry.key_type)
                    {
                        case CTC_SCL_KEY_HASH_PORT_SVLAN:
                            field_key.type = CTC_FIELD_KEY_SVLAN_ID;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->match_svlan = field_key.data;
                            break;
                        case CTC_SCL_KEY_HASH_PORT_2VLAN:
                            field_key.type = CTC_FIELD_KEY_SVLAN_ID;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->match_svlan = field_key.data;
                            field_key.type = CTC_FIELD_KEY_CVLAN_ID;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->match_cvlan = field_key.data;
                            break;
                        case SYS_SCL_KEY_HASH_PORT_SVLAN_COS:
                            field_key.type = CTC_FIELD_KEY_SVLAN_ID;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->pkt_svlan = field_key.data;
                            field_key.type = CTC_FIELD_KEY_STAG_COS;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->match_scos = field_key.data;
                            p_vlan_port_db->match_scos_valid = 1;
                            break;
                        default:
                            goto done;
                    }
                }
            }
        }
        else if(CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_FROM_UNI))
        {
            if (p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN_CVLAN || p_vlan_port_db->criteria == CTC_PON_VLAN_PORT_MATCH_SVLAN)
            {/*basic*/
                if (1 == p_vlan_port_db->egs_vlan_mapping_en && 0 == p_vlan_port_db->pass_through_en)/*down link*/
                {
                    scl_entry.entry_id = ENCODE_SCL_VLAN_ENTRY_ID(p_vlan_port_db->vlan_port_id);
                    CTC_ERROR_GOTO(sys_usw_scl_get_entry_by_id(lchip, &scl_entry),ret, done);
                    if(CTC_SCL_KEY_HASH_PORT_2VLAN != scl_entry.key_type)
                    {
                        ret = CTC_E_PARAM_CONFLICT;
                        goto done;
                    }
                    field_key.type = CTC_FIELD_KEY_SVLAN_ID;
                    CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                    p_vlan_port_db->pkt_svlan = field_key.data;
                    
                    if (!p_vlan_port_db->match_svlan_end)
                    {
                        field_key.type = CTC_FIELD_KEY_CVLAN_ID;
                        CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                        p_vlan_port_db->pkt_cvlan = field_key.data;
                    }
                }

                if (DRV_FROM_TMM(lchip)&& p_vlan_port_db->match_svlan_end)
                {
                    ctc_vlan_range_info_t range_info;
                    ctc_vlan_range_group_t vlan_range_group;
                    uint8 count = 0;
                    scl_entry.entry_id = ENCODE_SCL_UPLINK_ENTRY_ID(p_vlan_port_db->vlan_port_id, 0);
                    CTC_ERROR_GOTO(sys_usw_scl_get_entry_by_id(lchip, &scl_entry),ret, done);
                    if(CTC_SCL_KEY_TCAM_IPV4 != scl_entry.key_type)
                    {
                        ret = CTC_E_PARAM_CONFLICT;
                        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [PON] scl_entry.key_type is %d , line:%d\n", scl_entry.key_type, __LINE__);
                        goto done;
                    }
                    field_key.type = CTC_FIELD_KEY_CVLAN_ID;
                    CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                    p_vlan_port_db->match_cvlan = field_key.data;

                    sal_memset(&range_info, 0, sizeof(range_info));
                    sal_memset(&vlan_range_group, 0, sizeof(ctc_vlan_range_group_t));
                    range_info.direction = CTC_INGRESS;
                    range_info.vrange_grpid = p_usw_pon_master[lchip]->p_port_db[wb_vlan_port_db.lport].vlan_range_grp;
                    CTC_ERROR_GOTO(sys_usw_vlan_get_vlan_range_member(lchip, &range_info, &vlan_range_group, &count),ret,done);
                    while(count--)
                    {
                        if(vlan_range_group.vlan_range[count].vlan_end == p_vlan_port_db->match_svlan_end)
                        {
                            p_vlan_port_db->match_svlan = vlan_range_group.vlan_range[count].vlan_start;
                            break;
                        }
                    };
                }
                else
                {
                    scl_entry.entry_id = p_vlan_port_db->scl_eid;
                    CTC_ERROR_GOTO(sys_usw_scl_get_entry_by_id(lchip, &scl_entry),ret, done);
                    switch(scl_entry.key_type)
                    {
                        case CTC_SCL_KEY_HASH_PORT_SVLAN:
                            field_key.type = CTC_FIELD_KEY_SVLAN_ID;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->match_svlan = field_key.data;
                            break;
                        case CTC_SCL_KEY_HASH_PORT_2VLAN:
                            field_key.type = CTC_FIELD_KEY_SVLAN_ID;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->match_svlan = field_key.data;
                            field_key.type = CTC_FIELD_KEY_CVLAN_ID;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->match_cvlan = field_key.data;
                            break;
                        case SYS_SCL_KEY_HASH_PORT_SVLAN_COS:
                            field_key.type = CTC_FIELD_KEY_SVLAN_ID;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->pkt_svlan = field_key.data;
                            field_key.type = CTC_FIELD_KEY_STAG_COS;
                            CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                            p_vlan_port_db->match_scos = field_key.data;
                            p_vlan_port_db->match_scos_valid = 1;
                            break;
                        case SYS_SCL_KEY_HASH_PORT_CROSS:
                            break;
                        default:
                            goto done;
                    }
                    
                }
            }
            else /*flex*/
            {
                if(1 == p_vlan_port_db->egs_vlan_mapping_en)
                {
                    scl_entry.entry_id = ENCODE_SCL_VLAN_ENTRY_ID(p_vlan_port_db->vlan_port_id);
                    CTC_ERROR_GOTO(sys_usw_scl_get_entry_by_id(lchip, &scl_entry),ret, done);
                    if(CTC_SCL_KEY_HASH_PORT_2VLAN != scl_entry.key_type)
                    {
                        ret = CTC_E_PARAM_CONFLICT;
                        goto done;
                    }
                    field_key.type = CTC_FIELD_KEY_SVLAN_ID;
                    CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                    p_vlan_port_db->pkt_svlan = field_key.data;
                    
                    if (!p_vlan_port_db->match_svlan_end)
                    {
                        field_key.type = CTC_FIELD_KEY_CVLAN_ID;
                        CTC_ERROR_GOTO(sys_usw_scl_get_key_field(lchip,  p_vlan_port_db->scl_eid, &field_key),ret, done);
                        p_vlan_port_db->pkt_cvlan = field_key.data;
                    }
                }
            }
            
            scl_action.type= CTC_SCL_FIELD_ACTION_TYPE_VLAN_EDIT;
            scl_action.ext_data = &p_vlan_port_db->igs_vlan_action;
            sys_usw_scl_get_action_field(lchip, p_vlan_port_db->scl_eid, &scl_action);
            
        }
                    
        if(p_vlan_port_db->scl_id == 2)
        {
            p_usw_pon_master[lchip]->p_port_db[wb_vlan_port_db.lport].flex_pon_cnt++;
        }
        else if(p_vlan_port_db->scl_id == 3)
        {
            p_usw_pon_master[lchip]->p_port_db[wb_vlan_port_db.lport].flex_onu_cnt++;
        }

        sal_memset(&gem_port_db, 0, sizeof(gem_port_db));
        gem_port_db.gport = p_vlan_port_db->gport;
        gem_port_db.tunnel_value = p_vlan_port_db->tunnel_value;
        p_vlan_port_db->p_gem_port_db = ctc_hash_lookup(p_usw_pon_master[lchip]->gem_port_hash, &gem_port_db);
        if(!CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_PON_SERVICE) && CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_FROM_UNI))
        {
            p_vlan_port_db->p_gem_port_db->ref_cnt++;
        }

        
        scl_action.type = CTC_SCL_FIELD_ACTION_TYPE_FID;
        sys_usw_scl_get_action_field(lchip, p_vlan_port_db->scl_eid , &scl_action);
        p_vlan_port_db->fid = scl_action.data0;
        
        if(CTC_FLAG_ISSET(p_vlan_port_db->flag, CTC_PON_VLAN_PORT_FLAG_IGS_POLICER))
        {
            scl_action.type = CTC_SCL_FIELD_ACTION_TYPE_POLICER_ID;
            sys_usw_scl_get_action_field(lchip, p_vlan_port_db->scl_eid , &scl_action);
            p_vlan_port_db->igs_policer_id = scl_action.data0;
        }
        _sys_usw_pon_vlan_port_mapping_pkt_vlan(lchip, p_vlan_port_db, &p_vlan_port_db->igs_vlan_action);

        /*onu downstream*/
        if (p_vlan_port_db->xlate_nhid)
        {
            sal_memcpy(&p_vlan_port_db->egs_vlan_action, &wb_vlan_port_db.egs_vlan_action, sizeof(ctc_scl_vlan_edit_t));
        }
        
        ctc_hash_insert(p_usw_pon_master[lchip]->vlan_port_hash, (void*)(p_vlan_port_db));
        CTC_WB_QUERY_ENTRY_END((&wb_query));
    }

done:
    CTC_WB_FREE_BUFFER(wb_query.buffer);

    return ret;
}

int32
_sys_usw_pon_init_wb(uint8 lchip)
{
    ctc_wb_appid_t  appid;

    sal_memset(&appid,0,sizeof(appid));
    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_PORT);
    appid.entry_num = MCHIP_CAP(SYS_CAP_PORT_NUM);
    appid.entry_size  = sizeof(sys_wb_pon_port_db_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);
   
    sal_memset(&appid,0,sizeof(appid));
    if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_SCL))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_VLAN_PORT);
        appid.entry_num = SYS_WB_PON_VLAN_PORT_NUM;
        appid.entry_size  = sizeof(sys_wb_pon_vlan_port_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);
    }

    sal_memset(&appid,0,sizeof(appid));
    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_GEM_PORT);
    appid.entry_num = SYS_WB_PON_GEM_PORT_NUM;
    appid.entry_size  = sizeof(sys_wb_pon_gem_port_db_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    return 0;
}

int32
_sys_usw_pon_gem_port_dump(void* bucket_data, void* user_data)
{
    sys_traverse_t* data = (sys_traverse_t*)user_data;
    sal_file_t p_f = (sal_file_t) data->data1;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = data->value1;
#endif
    sys_pon_gem_port_db_t* p_gem_port_db = (sys_pon_gem_port_db_t*) bucket_data;
    SYS_DUMP_DB_LOG(p_f, "gport:%u", p_gem_port_db->gport);
    SYS_DUMP_DB_LOG(p_f, "  tunnel_value:%u", p_gem_port_db->tunnel_value);
    SYS_DUMP_DB_LOG(p_f, "  logic_port:%u", p_gem_port_db->logic_port);
    SYS_DUMP_DB_LOG(p_f, "  ref_cnt:%u", p_gem_port_db->ref_cnt);
    SYS_DUMP_DB_LOG(p_f, "  igs_policer_id:%u", p_gem_port_db->igs_policer_id);
    SYS_DUMP_DB_LOG(p_f, "  is_flooding:%u", p_gem_port_db->is_flooding);
    if(!p_gem_port_db->is_flooding)
    {
        SYS_DUMP_DB_LOG(p_f, "  egs_service_id:%u", p_gem_port_db->egs_service_id);
    }
    SYS_DUMP_DB_LOG(p_f, "  pass_through_en:%u", p_gem_port_db->pass_through_en);
    SYS_DUMP_DB_LOG(p_f, "  mac_security:%u\n", p_gem_port_db->mac_security);

    return CTC_E_NONE;
}

void _sys_usw_pon_vlan_edit_dump(uint8 lchip, sal_file_t p_f,ctc_scl_vlan_edit_t *p_vlan_edit)
{
    char  * tag_op[CTC_VLAN_TAG_OP_MAX];
    char  * tag_sl[CTC_VLAN_TAG_SL_MAX];
    char  * domain_sl[CTC_SCL_VLAN_DOMAIN_MAX];

    tag_op[CTC_VLAN_TAG_OP_NONE]       = "None";
    tag_op[CTC_VLAN_TAG_OP_REP_OR_ADD] = "Replace or Add";
    tag_op[CTC_VLAN_TAG_OP_ADD]        = "Add";
    tag_op[CTC_VLAN_TAG_OP_DEL]        = "Delete";
    tag_op[CTC_VLAN_TAG_OP_REP]        = "Replace";
    tag_op[CTC_VLAN_TAG_OP_VALID]      = "Valid";

    tag_sl[CTC_VLAN_TAG_SL_AS_PARSE]    = "As parser";
    tag_sl[CTC_VLAN_TAG_SL_ALTERNATIVE] = "Alternative";
    tag_sl[CTC_VLAN_TAG_SL_NEW]         = "New";
    tag_sl[CTC_VLAN_TAG_SL_DEFAULT]     = "Default";

    domain_sl[CTC_SCL_VLAN_DOMAIN_SVLAN]    = "Svlan domain";
    domain_sl[CTC_SCL_VLAN_DOMAIN_CVLAN]  = "Cvlan domain";
    domain_sl[CTC_SCL_VLAN_DOMAIN_UNCHANGE]  = "Unchange";

    if (p_vlan_edit->stag_op != CTC_VLAN_TAG_OP_NONE)
    {
        SYS_DUMP_DB_LOG(p_f, "%25s - %s\n", "Stag_op", tag_op[p_vlan_edit->stag_op]);

        if (p_vlan_edit->stag_op != CTC_VLAN_TAG_OP_DEL)
        {
            SYS_DUMP_DB_LOG(p_f,"%27s - %-12s  %s - %u\n", "svid_sl", tag_sl[p_vlan_edit->svid_sl], "New_svid", p_vlan_edit->svid_new);
            SYS_DUMP_DB_LOG(p_f,"%27s - %-12s  %s - %u\n", "scos_sl", tag_sl[p_vlan_edit->scos_sl], "New_scos", p_vlan_edit->scos_new);
            SYS_DUMP_DB_LOG(p_f,"%27s - %-12s  %s - %u\n", "scfi_sl", tag_sl[p_vlan_edit->scfi_sl], "New_scfi", p_vlan_edit->scfi_new);
            SYS_DUMP_DB_LOG(p_f,"%27s - %-12u\n", "tpid_idx", p_vlan_edit->tpid_index);
        }
    }
    if (p_vlan_edit->ctag_op != CTC_VLAN_TAG_OP_NONE)
    {
        SYS_DUMP_DB_LOG(p_f,"%25s - %s\n", "Ctag_op", tag_op[p_vlan_edit->ctag_op]);
        if (p_vlan_edit->ctag_op != CTC_VLAN_TAG_OP_DEL)
        {
            SYS_DUMP_DB_LOG(p_f,"%27s - %-12s  %s - %u\n", "cvid_sl", tag_sl[p_vlan_edit->cvid_sl], "New_cvid", p_vlan_edit->cvid_new);
            SYS_DUMP_DB_LOG(p_f,"%27s - %-12s  %s - %u\n", "ccos_sl", tag_sl[p_vlan_edit->ccos_sl], "New_ccos", p_vlan_edit->ccos_new);
            SYS_DUMP_DB_LOG(p_f,"%27s - %-12s  %s - %u\n", "ccfi_sl", tag_sl[p_vlan_edit->ccfi_sl], "New_ccfi", p_vlan_edit->ccfi_new);
        }
    }
    SYS_DUMP_DB_LOG(p_f, "%29s - %s\n\n", "Vlan domain", domain_sl[p_vlan_edit->vlan_domain]);

}

int32
_sys_usw_pon_vlan_port_dump(void* bucket_data, void* user_data)
{
    sys_traverse_t* data = (sys_traverse_t*)user_data;
    sal_file_t p_f = (sal_file_t) data->data1;
    uint8 lchip = data->value1;
    sys_pon_vlan_port_db_t* p_vlan_port_db = (sys_pon_vlan_port_db_t*) bucket_data;


    SYS_DUMP_DB_LOG(p_f, "VLAN PORT ID:%u\n", p_vlan_port_db->vlan_port_id);
    SYS_DUMP_DB_LOG(p_f, "  criteria:%u", p_vlan_port_db->criteria);
    SYS_DUMP_DB_LOG(p_f, "  scl_id:%u", p_vlan_port_db->scl_id);
    SYS_DUMP_DB_LOG(p_f, "  flag:0x%x", p_vlan_port_db->flag);
    SYS_DUMP_DB_LOG(p_f, "  gport:%u", p_vlan_port_db->gport);
    SYS_DUMP_DB_LOG(p_f, "  tunnel_value:%u\n", p_vlan_port_db->tunnel_value);
    SYS_DUMP_DB_LOG(p_f, "  match_svlan:%u", p_vlan_port_db->match_svlan);
    SYS_DUMP_DB_LOG(p_f, "  match_cvlan:%u", p_vlan_port_db->match_cvlan);
    SYS_DUMP_DB_LOG(p_f, "  match_scos:%u", p_vlan_port_db->match_scos);
    SYS_DUMP_DB_LOG(p_f, "  match_scos_valid:%u", p_vlan_port_db->match_scos_valid);
    SYS_DUMP_DB_LOG(p_f, "  match_svlan_end:%u", p_vlan_port_db->match_svlan_end);
    SYS_DUMP_DB_LOG(p_f, "  match_cvlan_end:%u", p_vlan_port_db->match_cvlan_end);
    SYS_DUMP_DB_LOG(p_f, "  pkt_svlan:%u", p_vlan_port_db->pkt_svlan);
    SYS_DUMP_DB_LOG(p_f, "  pkt_cvlan:%u\n", p_vlan_port_db->pkt_cvlan);
    SYS_DUMP_DB_LOG(p_f, "  logic_port:%u", p_vlan_port_db->logic_port);
    SYS_DUMP_DB_LOG(p_f, "  logic_dest_port:%u", p_vlan_port_db->logic_dest_port);
    SYS_DUMP_DB_LOG(p_f, "  acl_logic_port:%u", p_vlan_port_db->acl_logic_port);
    SYS_DUMP_DB_LOG(p_f, "  xlate_nhid:%u", p_vlan_port_db->xlate_nhid);
    SYS_DUMP_DB_LOG(p_f, "  vn_tag:%u", p_vlan_port_db->vn_tag);
    SYS_DUMP_DB_LOG(p_f, "  fid:%u\n", p_vlan_port_db->fid);
    SYS_DUMP_DB_LOG(p_f, "  igs_policer_id:%u", p_vlan_port_db->igs_policer_id);
    SYS_DUMP_DB_LOG(p_f, "  egs_vlan_mapping_en:%u", p_vlan_port_db->egs_vlan_mapping_en);
    SYS_DUMP_DB_LOG(p_f, "  pass_through_en:%u", p_vlan_port_db->pass_through_en);
    SYS_DUMP_DB_LOG(p_f, "  igs_vlan_mapping_use_flex:%u", p_vlan_port_db->igs_vlan_mapping_use_flex);
    SYS_DUMP_DB_LOG(p_f, "  scl_eid:%u\n", p_vlan_port_db->scl_eid);
    if(p_vlan_port_db->p_gem_port_db)
    {
        SYS_DUMP_DB_LOG(p_f, "  gemport_gport:%u    gemport_vlan:%u\n", p_vlan_port_db->p_gem_port_db->gport, p_vlan_port_db->p_gem_port_db->tunnel_value);
    }
    SYS_DUMP_DB_LOG(p_f, "  %-16s: \n", "ingress VLAN_EDIT");
    _sys_usw_pon_vlan_edit_dump(lchip, p_f, &p_vlan_port_db->igs_vlan_action);
    SYS_DUMP_DB_LOG(p_f, "  %-16s: \n", "engress VLAN_EDIT");
    _sys_usw_pon_vlan_edit_dump(lchip, p_f, &p_vlan_port_db->egs_vlan_action);
    SYS_DUMP_DB_LOG(p_f, "--------------------------------------\n");
    return CTC_E_NONE;
}


int32
sys_usw_pon_dump_db(uint8 lchip, sal_file_t p_f, ctc_global_dump_db_t* p_dump_param)
{
    uint32 loop = 0;
    sys_traverse_t traverse_data;
    SYS_PON_INIT_CHECK(lchip);

    SYS_PON_LOCK(lchip);
    sal_memset(&traverse_data, 0, sizeof(sys_traverse_t));
    traverse_data.value1 = lchip;
    traverse_data.data1 = (void*)p_f;
    SYS_DUMP_DB_LOG(p_f, "%s\n", "# PON");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "==========================GEM PORT=========================="); 
    ctc_hash_traverse(p_usw_pon_master[lchip]->gem_port_hash, _sys_usw_pon_gem_port_dump, (void*)(&traverse_data));
    SYS_DUMP_DB_LOG(p_f, "%s\n", "==========================VLAN PORT=========================="); 
    ctc_hash_traverse(p_usw_pon_master[lchip]->vlan_port_hash, _sys_usw_pon_vlan_port_dump, (void*)(&traverse_data));
    SYS_DUMP_DB_LOG(p_f, "%s\n", "==========================PORT DB=========================="); 
    for(loop = 0; loop < MCHIP_CAP(SYS_CAP_PORT_NUM); loop++)
    {
        if(!p_usw_pon_master[lchip]->p_port_db[loop].enable)
        {
            continue;
        }
        SYS_DUMP_DB_LOG(p_f, "lport: %u\n", loop);
        SYS_DUMP_DB_LOG(p_f, "vlan_range_grp: %u\n", p_usw_pon_master[lchip]->p_port_db[loop].vlan_range_grp);
        SYS_DUMP_DB_LOG(p_f, "flex_onu_cnt: %u\n", p_usw_pon_master[lchip]->p_port_db[loop].flex_onu_cnt);
        SYS_DUMP_DB_LOG(p_f, "flex_pon_cnt: %u\n", p_usw_pon_master[lchip]->p_port_db[loop].flex_pon_cnt);
        SYS_DUMP_DB_LOG(p_f, "logic_port: %u\n\n", p_usw_pon_master[lchip]->p_port_db[loop].logic_port);
    }
    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");
    SYS_PON_UNLOCK(lchip);

    return CTC_E_NONE;
}

/*Init*/
int32
sys_usw_pon_init(uint8 lchip, void* p_init_cfg)
{
    int32 ret = 0;
    uint16 i = 0;
    sys_usw_opf_t opf;
    uint32 gem_port_num = 0;
    uint32 entry_num = 0;
    LCHIP_CHECK(lchip);
    if (p_usw_pon_master[lchip]) /*already init */
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT(lchip, p_usw_pon_master, CTC_FEATURE_PON);
    MALLOC_ZERO(MEM_PON_MODULE, p_usw_pon_master[lchip], sizeof(sys_pon_master_t));
    if (!p_usw_pon_master[lchip])
    {
        SYS_PON_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    if(!((SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A && DRV_IS_TSINGMA(lchip)) || DRV_IS_TMM(lchip)) && ((ctc_pon_global_cfg_t*)p_init_cfg)->mode)
    {
        ret = CTC_E_NOT_SUPPORT;
        goto roll_back_0;
    }
    else if (DRV_FROM_AT(lchip))
    {
        uint32 cmd = 0;
        uint32 field_val = 1;
        cmd = DRV_IOW(UserIdCtl_t, UserIdCtl_lportMaskEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
        return CTC_E_NONE;
    }
    CTC_ERROR_RETURN(sys_usw_ftm_query_table_entry_num(lchip, DsGemPortHashKey_t, &entry_num));
    if (!entry_num)
    {
        ret = CTC_E_NO_RESOURCE;
        goto roll_back_0;
    }

    p_usw_pon_master[lchip]->pon_mode = ((ctc_pon_global_cfg_t*)p_init_cfg)->mode;
    p_usw_pon_master[lchip]->gem_port_hash = ctc_hash_create(32,1024, (hash_key_fn) _sys_usw_pon_gem_port_hash_make,
                                                              (hash_cmp_fn) _sys_usw_pon_gem_port_hash_cmp);
    if (NULL == p_usw_pon_master[lchip]->gem_port_hash)
    {
        ret = CTC_E_NO_MEMORY;
        goto roll_back_0;
    }

    if (2 == p_usw_pon_master[lchip]->pon_mode)
    {
        gem_port_num = ((ctc_pon_global_cfg_t*)p_init_cfg)->gem_port_num? ((ctc_pon_global_cfg_t*)p_init_cfg)->gem_port_num : 16*1024;
        if(8 > gem_port_num || MCHIP_CAP(SYS_CAP_NH_MAX_LOGIC_DEST_PORT)+1 < gem_port_num)  /* DsL2EditGemPort contain 8 gemvlan */
        {
            ret = CTC_E_INVALID_PARAM;
            goto roll_back_0;
        }
    }
    else
    {
        p_usw_pon_master[lchip]->vlan_port_hash = ctc_hash_create(32,1024, (hash_key_fn) _sys_usw_pon_vlan_port_hash_make,
                                                                   (hash_cmp_fn) _sys_usw_pon_vlan_port_hash_cmp);
        if (NULL == p_usw_pon_master[lchip]->vlan_port_hash)
        {
            ret = CTC_E_NO_MEMORY;
            goto roll_back_0;
        }
    }

    p_usw_pon_master[lchip]->p_port_db = (sys_pon_port_db_t*)mem_malloc(MEM_PON_MODULE, MCHIP_CAP(SYS_CAP_PORT_NUM)*sizeof(sys_pon_port_db_t));
    if (NULL == p_usw_pon_master[lchip]->p_port_db)
    {
         ret = CTC_E_NO_MEMORY;
        goto roll_back_0;
    }

    sal_memset(p_usw_pon_master[lchip]->p_port_db, 0, MCHIP_CAP(SYS_CAP_PORT_NUM)*sizeof(sys_pon_port_db_t));
    for(; i< MCHIP_CAP(SYS_CAP_PORT_NUM); i++)
    {
        p_usw_pon_master[lchip]->p_port_db[i].vlan_range_grp = 0xFF;
    }

    CTC_ERROR_GOTO(sys_usw_opf_init(lchip, &p_usw_pon_master[lchip]->opf_vlan_range_group_id, 1, "opf-vlan-range-group-id"), ret, roll_back_0);
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type = p_usw_pon_master[lchip]->opf_vlan_range_group_id;
    opf.pool_index = 0;
    CTC_ERROR_GOTO(sys_usw_opf_init_offset(lchip, &opf, 0, 16), ret , roll_back_1);

    sal_mutex_create(&p_usw_pon_master[lchip]->mutex);

    sys_usw_global_set_xgpon_en(lchip, TRUE, p_usw_pon_master[lchip]->pon_mode);

    sys_usw_nh_set_xgpon_en(lchip, TRUE, gem_port_num);

    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_PON);

    if(p_usw_pon_master[lchip]->pon_mode == 1)
    {
        sys_usw_pon_init_scl_lookup(lchip);
    }

    CTC_ERROR_GOTO(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_PON, SYS_WB_APPID_PON_SUBID_MAX,sys_usw_pon_wb_sync), ret, roll_back_1);

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        CTC_ERROR_GOTO(sys_usw_pon_wb_restore(lchip), ret, roll_back_1);
    }
    if(CTC_WB_ENABLE(lchip))
    {
         _sys_usw_pon_init_wb(lchip);
    }  
    CTC_ERROR_GOTO(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_PON, sys_usw_pon_dump_db), ret, roll_back_1);

    return CTC_E_NONE;
roll_back_1:

    sys_usw_opf_deinit(lchip, p_usw_pon_master[lchip]->opf_vlan_range_group_id);

roll_back_0:

    if (p_usw_pon_master[lchip]->p_port_db)
    {
        mem_free(p_usw_pon_master[lchip]->p_port_db);
    }

    if (p_usw_pon_master[lchip]->vlan_port_hash)
    {
         ctc_hash_free(p_usw_pon_master[lchip]->vlan_port_hash);
    }

    if (p_usw_pon_master[lchip]->gem_port_hash)
    {
         ctc_hash_free(p_usw_pon_master[lchip]->gem_port_hash);
    }

    if (p_usw_pon_master[lchip])
    {
        mem_free(p_usw_pon_master[lchip]);
        p_usw_pon_master[lchip] = NULL;
    }

    return ret;
}

STATIC int32
_sys_usw_pon_free_node_data(void* node_data, void* user_data)
{
    if (node_data)
    {
        mem_free(node_data);
    }
    return 1;
}

int32
sys_usw_pon_deinit(uint8 lchip, void* p_init_cfg)
{
    LCHIP_CHECK(lchip);
    if (NULL == p_usw_pon_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, p_usw_pon_master, CTC_FEATURE_PON);
    if (!DRV_FROM_AT(lchip))
    {
        sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_PON,0, NULL);
        sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_PON, NULL);
        mem_free(p_usw_pon_master[lchip]->p_port_db);
        ctc_hash_free2(p_usw_pon_master[lchip]->vlan_port_hash, (hash_traversal_fn)_sys_usw_pon_free_node_data, NULL);
        ctc_hash_free2(p_usw_pon_master[lchip]->gem_port_hash, (hash_traversal_fn)_sys_usw_pon_free_node_data, NULL);
        sys_usw_opf_deinit(lchip, p_usw_pon_master[lchip]->opf_vlan_range_group_id);

        sal_mutex_destroy(p_usw_pon_master[lchip]->mutex);
    }

    mem_free(p_usw_pon_master[lchip]);

    return CTC_E_NONE;
}
#endif

